mirror of
https://github.com/fish-shell/fish-shell
synced 2024-11-10 15:14:44 +00:00
parent
37508d1f1e
commit
5b6814d6ad
7 changed files with 504 additions and 99 deletions
|
@ -9,6 +9,7 @@
|
|||
- When the current token has an open single-quote (`'`), fish will now escape any `'` and `\` in pasted text so that it can be used as a single token. Note that this requires either bracketed paste or use of the special `fish_clipboard_paste` function (bound to \cv by default).
|
||||
- Fish is now more forgiving of missing or invalid $TERM values (#3850).
|
||||
- The `string` command now supports a `repeat` subcommand with the obvious behavior (#3864).
|
||||
- The `string match` command now supports a `--filter` flag to emit the entire string partially matched by a pattern (#3957).
|
||||
- The `functions --metadata --verbose` output now includes the function description (#597).
|
||||
- Completions for `helm` added (#3829).
|
||||
- Empty components in $CDPATH, $MANPATH and $PATH are now converted to "." (#2106, #3914).
|
||||
|
|
|
@ -11,11 +11,11 @@ string join [(-q | --quiet)] SEP [STRING...]
|
|||
string trim [(-l | --left)] [(-r | --right)] [(-c | --chars CHARS)]
|
||||
[(-q | --quiet)] [STRING...]
|
||||
string escape [(-n | --no-quoted)] [STRING...]
|
||||
string match [(-a | --all)] [(-i | --ignore-case)] [(-r | --regex)]
|
||||
string match [(-a | --all)] [((-f | --filter)] [(-i | --ignore-case)] [(-r | --regex)]
|
||||
[(-n | --index)] [(-q | --quiet)] [(-v | --invert)] PATTERN [STRING...]
|
||||
string replace [(-a | --all)] [(-i | --ignore-case)] [(-r | --regex)]
|
||||
[(-q | --quiet)] PATTERN REPLACEMENT [STRING...]
|
||||
string repeat [(-n | --count)] [(-m | --max)] [(-N | --no-newline)]
|
||||
string repeat [(-n | --count)] [(-m | --max)] [(-N | --no-newline)]
|
||||
[(-q | --quiet)] [STRING...]
|
||||
\endfish
|
||||
|
||||
|
@ -32,25 +32,55 @@ Most subcommands accept a `-q` or `--quiet` switch, which suppresses the usual o
|
|||
|
||||
In addition to the exit codes documented below, all the string subcommands exit with a value of 2 to indicate that an error occurred.
|
||||
|
||||
The following subcommands are available:
|
||||
The following subcommands are available.
|
||||
|
||||
- `length` reports the length of each string argument in characters. Exit status: 0 if at least one non-empty STRING was given, or 1 otherwise.
|
||||
\subsection string-length "length" subcommand
|
||||
|
||||
- `sub` prints a substring of each string argument. The start of the substring can be specified with `-s` or `--start` followed by a 1-based index value. Positive index values are relative to the start of the string and negative index values are relative to the end of the string. The default start value is 1. The length of the substring can be specified with `-l` or `--length`. If the length is not specified, the substring continues to the end of each STRING. Exit status: 0 if at least one substring operation was performed, 1 otherwise.
|
||||
"`string length`" reports the length of each string argument in characters. Exit status: 0 if at least one non-empty STRING was given, or 1 otherwise.
|
||||
|
||||
- `split` splits each STRING on the separator SEP, which can be an empty string. If `-m` or `--max` is specified, at most MAX splits are done on each STRING. If `-r` or `--right` is given, splitting is performed right-to-left. This is useful in combination with `-m` or `--max`. Exit status: 0 if at least one split was performed, or 1 otherwise.
|
||||
\subsection string-sub "sub" subcommand
|
||||
|
||||
- `join` joins its STRING arguments into a single string separated by SEP, which can be an empty string. Exit status: 0 if at least one join was performed, or 1 otherwise.
|
||||
"`string sub`" prints a substring of each string argument. The start of the substring can be specified with `-s` or `--start` followed by a 1-based index value. Positive index values are relative to the start of the string and negative index values are relative to the end of the string. The default start value is 1. The length of the substring can be specified with `-l` or `--length`. If the length is not specified, the substring continues to the end of each STRING. Exit status: 0 if at least one substring operation was performed, 1 otherwise.
|
||||
|
||||
- `trim` removes leading and trailing whitespace from each STRING. If `-l` or `--left` is given, only leading whitespace is removed. If `-r` or `--right` is given, only trailing whitespace is trimmed. The `-c` or `--chars` switch causes the characters in CHARS to be removed instead of whitespace. Exit status: 0 if at least one character was trimmed, or 1 otherwise.
|
||||
\subsection string-split "split" subcommand
|
||||
|
||||
- `escape` escapes each STRING such that it can be passed back to `eval` to produce the original argument again. By default, all special characters are escaped, and quotes are used to simplify the output when possible. If `-n` or `--no-quoted` is given, the simplifying quoted format is not used. Exit status: 0 if at least one string was escaped, or 1 otherwise.
|
||||
"`string split`" splits each STRING on the separator SEP, which can be an empty string. If `-m` or `--max` is specified, at most MAX splits are done on each STRING. If `-r` or `--right` is given, splitting is performed right-to-left. This is useful in combination with `-m` or `--max`. Exit status: 0 if at least one split was performed, or 1 otherwise.
|
||||
|
||||
- `match` tests each STRING against PATTERN and prints matching substrings. Only the first match for each STRING is reported unless `-a` or `--all` is given, in which case all matches are reported. Matching can be made case-insensitive with `-i` or `--ignore-case`. If `-n` or `--index` is given, each match is reported as a 1-based start position and a length. By default, PATTERN is interpreted as a glob pattern matched against each entire STRING argument. A glob pattern is only considered a valid match if it matches the entire STRING. If `-r` or `--regex` is given, PATTERN is interpreted as a Perl-compatible regular expression, which does not have to match the entire STRING. For a regular expression containing capturing groups, multiple items will be reported for each match, one for the entire match and one for each capturing group. If --invert or -v is used the selected lines will be only those which do not match the given glob pattern or regular expression. Exit status: 0 if at least one match was found, or 1 otherwise.
|
||||
\subsection string-join "join" subcommand
|
||||
|
||||
- `replace` is similar to `match` but replaces non-overlapping matching substrings with a replacement string and prints the result. By default, PATTERN is treated as a literal substring to be matched. If `-r` or `--regex` is given, PATTERN is interpreted as a Perl-compatible regular expression, and REPLACEMENT can contain C-style escape sequences like `\t` as well as references to capturing groups by number or name as `$n` or `${n}`. Exit status: 0 if at least one replacement was performed, or 1 otherwise.
|
||||
"`string join`" joins its STRING arguments into a single string separated by SEP, which can be an empty string. Exit status: 0 if at least one join was performed, or 1 otherwise.
|
||||
|
||||
- `repeat` repeats the STRING `-n` or `--count` times. The `-m` or `--max` option will limit the number of outputed char (excluding the newline). This option can be used by itself or in conjuction with `--count`. If both `--count` and `--max` are present, max char will be outputed unless the final repeated string size is less than max, in that case, the string will repeat until count has been reached. Both `--count` and `--max` will accept a number greater than or equal to zero, in the case of zero, nothing will be outputed. If `-N` or `--no-newline` is given, the output won't contain a newline character at the end. Exit status: 0 if yielded string is not empty, 1 otherwise.
|
||||
\subsection string-trim "trim" subcommand
|
||||
|
||||
"`string trim`" removes leading and trailing whitespace from each STRING. If `-l` or `--left` is given, only leading whitespace is removed. If `-r` or `--right` is given, only trailing whitespace is trimmed. The `-c` or `--chars` switch causes the characters in CHARS to be removed instead of whitespace. Exit status: 0 if at least one character was trimmed, or 1 otherwise.
|
||||
|
||||
\subsection string-escape "escape" subcommand
|
||||
|
||||
"`string escape`" escapes each STRING such that it can be passed back to `eval` to produce the original argument again. By default, all special characters are escaped, and quotes are used to simplify the output when possible. If `-n` or `--no-quoted` is given, the simplifying quoted format is not used. Exit status: 0 if at least one string was escaped, or 1 otherwise.
|
||||
|
||||
\subsection string-match "match" subcommand
|
||||
|
||||
"`string match`" tests each STRING against PATTERN and prints matching substrings. Only the first match for each STRING is reported unless `-a` or `--all` is given, in which case all matches are reported.The default behavior is equivalent to `grep -o`.
|
||||
|
||||
If you specify the `-f` or `--filter` then each matching string is printed including any prefix or suffix not matched by the pattern (equivalent to `grep` without the `-o` flag). You can, obviously, achieve the same result by prepending and appending `*` or `.*` depending on whether or not you have specified the `--regex` flag. The `--filter` flag is simply a way to avoid having to complicate the pattern in that fashion and make the intent of the `string match` clearer.
|
||||
|
||||
Matching can be made case-insensitive with `--ignore-case` or `-i`.
|
||||
|
||||
If `--index` or `-n` is given, each match is reported as a 1-based start position and a length. By default, PATTERN is interpreted as a glob pattern matched against each entire STRING argument. A glob pattern is only considered a valid match if it matches the entire STRING.
|
||||
|
||||
If `--regex` or `-r` is given, PATTERN is interpreted as a Perl-compatible regular expression, which does not have to match the entire STRING. For a regular expression containing capturing groups, multiple items will be reported for each match, one for the entire match and one for each capturing group.
|
||||
|
||||
If `--invert` or `-v` is used the selected lines will be only those which do not match the given glob pattern or regular expression.
|
||||
|
||||
Exit status: 0 if at least one match was found, or 1 otherwise.
|
||||
|
||||
\subsection string-replace "replace" subcommand
|
||||
|
||||
"`string replace`" is similar to `string match` but replaces non-overlapping matching substrings with a replacement string and prints the result. By default, PATTERN is treated as a literal substring to be matched. If `-r` or `--regex` is given, PATTERN is interpreted as a Perl-compatible regular expression, and REPLACEMENT can contain C-style escape sequences like `\t` as well as references to capturing groups by number or name as `$n` or `${n}`. Exit status: 0 if at least one replacement was performed, or 1 otherwise.
|
||||
|
||||
\subsection string-repeat "repeat" subcommand
|
||||
|
||||
"`string repeat`" repeats the STRING `-n` or `--count` times. The `-m` or `--max` option will limit the number of outputed char (excluding the newline). This option can be used by itself or in conjuction with `--count`. If both `--count` and `--max` are present, max char will be outputed unless the final repeated string size is less than max, in that case, the string will repeat until count has been reached. Both `--count` and `--max` will accept a number greater than or equal to zero, in the case of zero, nothing will be outputed. If `-N` or `--no-newline` is given, the output won't contain a newline character at the end. Exit status: 0 if yielded string is not empty, 1 otherwise.
|
||||
|
||||
\subsection regular-expressions Regular Expressions
|
||||
|
||||
|
|
|
@ -264,13 +264,19 @@ static int string_length(parser_t &parser, io_streams_t &streams, int argc, wcha
|
|||
|
||||
struct match_options_t {
|
||||
bool all;
|
||||
bool filter;
|
||||
bool ignore_case;
|
||||
bool index;
|
||||
bool invert_match;
|
||||
bool quiet;
|
||||
|
||||
match_options_t()
|
||||
: all(false), ignore_case(false), index(false), invert_match(false), quiet(false) {}
|
||||
: all(false),
|
||||
filter(false),
|
||||
ignore_case(false),
|
||||
index(false),
|
||||
invert_match(false),
|
||||
quiet(false) {}
|
||||
};
|
||||
|
||||
class string_matcher_t {
|
||||
|
@ -301,6 +307,12 @@ class wildcard_matcher_t : public string_matcher_t {
|
|||
wcpattern[i] = towlower(wcpattern[i]);
|
||||
}
|
||||
}
|
||||
if (opts.filter) {
|
||||
if (!wcpattern.empty()) {
|
||||
if (wcpattern.front() != ANY_STRING) wcpattern.insert(0, 1, ANY_STRING);
|
||||
if (wcpattern.back() != ANY_STRING) wcpattern.push_back(ANY_STRING);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
virtual ~wildcard_matcher_t() {}
|
||||
|
@ -407,14 +419,17 @@ class pcre2_matcher_t : public string_matcher_t {
|
|||
// The output vector wasn't big enough. Should not happen.
|
||||
string_error(streams, _(L"%ls: Regular expression internal error\n"), argv0);
|
||||
return -1;
|
||||
} else if (opts.invert_match) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
else if (opts.invert_match)
|
||||
return 0;
|
||||
if (opts.filter) {
|
||||
streams.out.append(arg);
|
||||
streams.out.push_back(L'\n');
|
||||
}
|
||||
|
||||
PCRE2_SIZE *ovector = pcre2_get_ovector_pointer(regex.match);
|
||||
|
||||
for (int j = 0; j < pcre2_rc; j++) {
|
||||
for (int j = (opts.filter ? 1 : 0); j < pcre2_rc; j++) {
|
||||
PCRE2_SIZE begin = ovector[2 * j];
|
||||
PCRE2_SIZE end = ovector[2 * j + 1];
|
||||
|
||||
|
@ -422,8 +437,8 @@ class pcre2_matcher_t : public string_matcher_t {
|
|||
if (opts.index) {
|
||||
streams.out.append_format(L"%lu %lu", (unsigned long)(begin + 1),
|
||||
(unsigned long)(end - begin));
|
||||
} else if (end > begin) // may have end < begin if \K is used
|
||||
{
|
||||
} else if (end > begin) {
|
||||
// May have end < begin if \K is used.
|
||||
streams.out.append(wcstring(&arg[begin], end - begin));
|
||||
}
|
||||
streams.out.push_back(L'\n');
|
||||
|
@ -501,32 +516,28 @@ class pcre2_matcher_t : public string_matcher_t {
|
|||
};
|
||||
|
||||
static int string_match(parser_t &parser, io_streams_t &streams, int argc, wchar_t **argv) {
|
||||
const wchar_t *short_options = L"ainvqr";
|
||||
const struct woption long_options[] = {{L"all", no_argument, 0, 'a'},
|
||||
{L"ignore-case", no_argument, 0, 'i'},
|
||||
{L"index", no_argument, 0, 'n'},
|
||||
{L"invert", no_argument, 0, 'v'},
|
||||
{L"quiet", no_argument, 0, 'q'},
|
||||
{L"regex", no_argument, 0, 'r'},
|
||||
{0, 0, 0, 0}};
|
||||
wchar_t *cmd = argv[0];
|
||||
const wchar_t *short_options = L"afinqrv";
|
||||
const struct woption long_options[] = {
|
||||
{L"all", no_argument, NULL, 'a'}, {L"filter", no_argument, NULL, 'f'},
|
||||
{L"ignore-case", no_argument, NULL, 'i'}, {L"index", no_argument, NULL, 'n'},
|
||||
{L"invert", no_argument, NULL, 'v'}, {L"quiet", no_argument, NULL, 'q'},
|
||||
{L"regex", no_argument, NULL, 'r'}, {NULL, 0, NULL, 0}};
|
||||
|
||||
match_options_t opts;
|
||||
bool regex = false;
|
||||
int opt;
|
||||
wgetopter_t w;
|
||||
for (;;) {
|
||||
int opt = w.wgetopt_long(argc, argv, short_options, long_options, 0);
|
||||
|
||||
if (opt == -1) {
|
||||
break;
|
||||
}
|
||||
while ((opt = w.wgetopt_long(argc, argv, short_options, long_options, NULL)) != -1) {
|
||||
switch (opt) {
|
||||
case 0: {
|
||||
break;
|
||||
}
|
||||
case 'a': {
|
||||
opts.all = true;
|
||||
break;
|
||||
}
|
||||
case 'f': {
|
||||
opts.filter = true;
|
||||
break;
|
||||
}
|
||||
case 'i': {
|
||||
opts.ignore_case = true;
|
||||
break;
|
||||
|
@ -548,16 +559,22 @@ static int string_match(parser_t &parser, io_streams_t &streams, int argc, wchar
|
|||
break;
|
||||
}
|
||||
case '?': {
|
||||
string_unknown_option(parser, streams, argv[0], argv[w.woptind - 1]);
|
||||
string_unknown_option(parser, streams, cmd, argv[w.woptind - 1]);
|
||||
return BUILTIN_STRING_ERROR;
|
||||
}
|
||||
default: {
|
||||
DIE("unexpected opt");
|
||||
DIE("unexpected retval from wgetopt_long");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (opts.filter && opts.index) {
|
||||
streams.err.append_format(BUILTIN_ERR_COMBO2, cmd,
|
||||
_(L"--filter and --index are mutually exclusive"));
|
||||
return BUILTIN_STRING_ERROR;
|
||||
}
|
||||
|
||||
int i = w.woptind;
|
||||
const wchar_t *pattern;
|
||||
if ((pattern = string_get_arg_argv(&i, argv)) == 0) {
|
||||
|
@ -572,9 +589,9 @@ static int string_match(parser_t &parser, io_streams_t &streams, int argc, wchar
|
|||
|
||||
std::unique_ptr<string_matcher_t> matcher;
|
||||
if (regex) {
|
||||
matcher = make_unique<pcre2_matcher_t>(argv[0], pattern, opts, streams);
|
||||
matcher = make_unique<pcre2_matcher_t>(cmd, pattern, opts, streams);
|
||||
} else {
|
||||
matcher = make_unique<wildcard_matcher_t>(argv[0], pattern, opts, streams);
|
||||
matcher = make_unique<wildcard_matcher_t>(cmd, pattern, opts, streams);
|
||||
}
|
||||
|
||||
const wchar_t *arg;
|
||||
|
|
|
@ -499,9 +499,9 @@ wcstring parser_t::current_line() {
|
|||
append_format(prefix, _(L"%ls (line %d): "), user_presentable_path(file).c_str(),
|
||||
lineno);
|
||||
} else if (is_within_fish_initialization) {
|
||||
append_format(prefix, L"%ls: ", _(L"Startup"), lineno);
|
||||
append_format(prefix, L"%ls (line %d): ", _(L"Startup"), lineno);
|
||||
} else {
|
||||
append_format(prefix, L"%ls: ", _(L"Standard input"), lineno);
|
||||
append_format(prefix, L"%ls (line %d): ", _(L"Standard input"), lineno);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,34 @@
|
|||
# string match -r "[" "a[sd"
|
||||
string match: Regular expression compile error: missing terminating ] for character class
|
||||
string match: [
|
||||
string match: ^
|
||||
|
||||
# string invalidarg
|
||||
string: Unknown subcommand 'invalidarg'
|
||||
Standard input (line 167):
|
||||
string invalidarg; and echo "unexpected exit 0" >&2
|
||||
^
|
||||
|
||||
# string repeat -n-1 "foo"
|
||||
string repeat: Invalid count value '-1'
|
||||
|
||||
# string repeat -m-1 "foo"
|
||||
string repeat: Invalid max value '-1'
|
||||
|
||||
# string repeat -n notanumber "foo"
|
||||
string repeat: Argument 'notanumber' is not a number
|
||||
|
||||
# string repeat -m notanumber "foo"
|
||||
string repeat: Argument 'notanumber' is not a number
|
||||
|
||||
# echo "stdin" | string repeat -n1 "and arg"
|
||||
string repeat: Too many arguments
|
||||
|
||||
# string repeat -n
|
||||
string repeat: Expected argument
|
||||
|
||||
# string repeat -l fakearg 2>&1
|
||||
string repeat: Unknown option '-l'
|
||||
Standard input (line 268):
|
||||
string repeat -l fakearg
|
||||
^
|
||||
|
|
262
tests/string.in
262
tests/string.in
|
@ -1,143 +1,311 @@
|
|||
# tests for string builtin
|
||||
# mostly taken from examples
|
||||
# Tests for string builtin. Mostly taken from man page examples.
|
||||
|
||||
# We don't want syntax errors to emit command usage help. This makes the
|
||||
# stderr output considerably shorter and makes it easier to updates the tests
|
||||
# and documentation without having to make pointless changes to the test
|
||||
# output files.
|
||||
function __fish_print_help
|
||||
end
|
||||
|
||||
echo '# string match -r -v "c.*" dog can cat diz'
|
||||
string match -r -v "c.*" dog can cat diz; and echo "exit 0"
|
||||
|
||||
echo
|
||||
echo '# string match -q -r -v "c.*" dog can cat diz'
|
||||
string match -q -r -v "c.*" dog can cat diz; and echo "exit 0"
|
||||
|
||||
echo
|
||||
echo '# string match -v "c*" dog can cat diz'
|
||||
string match -v "c*" dog can cat diz; and echo "exit 0"
|
||||
|
||||
echo
|
||||
echo '# string match -q -v "c*" dog can cat diz'
|
||||
string match -q -v "c*" dog can cat diz; and echo "exit 0"
|
||||
|
||||
echo
|
||||
echo '# string match -v "d*" dog dan dat diz'
|
||||
string match -v "d*" dog dan dat diz; or echo "exit 1"
|
||||
|
||||
echo
|
||||
echo '# string match -q -v "d*" dog dan dat diz'
|
||||
string match -q -v "d*" dog dan dat diz; or echo "exit 1"
|
||||
|
||||
echo
|
||||
echo '# string match -r -v x y'
|
||||
string match -r -v x y; and echo "exit 0"
|
||||
|
||||
echo
|
||||
echo '# string match -r -v x x'
|
||||
string match -r -v x x; or echo "exit 1"
|
||||
|
||||
echo
|
||||
echo '# string match -q -r -v x y'
|
||||
string match -q -r -v x y; and echo "exit 0"
|
||||
|
||||
echo
|
||||
echo '# string match -q -r -v x x'
|
||||
string match -q -r -v x x; or echo "exit 1"
|
||||
|
||||
string length 'hello, world'
|
||||
echo
|
||||
echo '# string length "hello, world"'
|
||||
string length "hello, world"
|
||||
|
||||
string length -q ""; and echo not zero length
|
||||
echo
|
||||
echo '# string length -q ""'
|
||||
string length -q ""; and echo not zero length; or echo zero length
|
||||
|
||||
echo
|
||||
echo '# string sub --length 2 abcde'
|
||||
string sub --length 2 abcde
|
||||
|
||||
echo
|
||||
echo '# string sub -s 2 -l 2 abcde'
|
||||
string sub -s 2 -l 2 abcde
|
||||
|
||||
echo
|
||||
echo '# string sub --start=-2 abcde'
|
||||
string sub --start=-2 abcde
|
||||
|
||||
echo
|
||||
echo '# string split . example.com'
|
||||
string split . example.com
|
||||
|
||||
echo
|
||||
echo '# string split -r -m1 / /usr/local/bin/fish'
|
||||
string split -r -m1 / /usr/local/bin/fish
|
||||
|
||||
string split '' abc
|
||||
echo
|
||||
echo '# string split "" abc'
|
||||
string split "" abc
|
||||
|
||||
echo
|
||||
echo '# seq 3 | string join ...'
|
||||
seq 3 | string join ...
|
||||
|
||||
echo ' abc '
|
||||
string trim ' abc '
|
||||
echo
|
||||
echo '# string trim " abc "'
|
||||
string trim " abc "
|
||||
|
||||
echo
|
||||
echo '# string trim --right --chars=yz xyzzy zany'
|
||||
string trim --right --chars=yz xyzzy zany
|
||||
|
||||
echo
|
||||
echo '# echo \x07 | string escape'
|
||||
echo \x07 | string escape
|
||||
|
||||
string match '?' a
|
||||
echo
|
||||
echo '# string match "?" a'
|
||||
string match "?" a
|
||||
|
||||
string match 'a*b' axxb
|
||||
echo
|
||||
echo '# string match "a*b" axxb'
|
||||
string match "a*b" axxb
|
||||
|
||||
string match -i 'a??B' Axxb
|
||||
echo
|
||||
echo '# string match -i "a??B" Axxb'
|
||||
string match -i "a??B" Axxb
|
||||
|
||||
echo 'ok?' | string match '*\?'
|
||||
echo
|
||||
echo '# echo "ok?" | string match "*\?"'
|
||||
echo "ok?" | string match "*\?"
|
||||
|
||||
string match -r 'cat|dog|fish' 'nice dog'
|
||||
echo
|
||||
echo '# string match -r "cat|dog|fish" "nice dog"'
|
||||
string match -r "cat|dog|fish" "nice dog"
|
||||
|
||||
string match -r '(\d\d?):(\d\d):(\d\d)' 2:34:56
|
||||
echo
|
||||
echo '# string match -r "(\d\d?):(\d\d):(\d\d)" 2:34:56'
|
||||
string match -r "(\d\d?):(\d\d):(\d\d)" 2:34:56
|
||||
|
||||
string match -r '^(\w{2,4})\g1$' papa mud murmur
|
||||
echo
|
||||
echo '# string match -r "^(\w{2,4})\g1\$" papa mud murmur'
|
||||
string match -r "^(\w{2,4})\g1\$" papa mud murmur
|
||||
|
||||
echo
|
||||
echo '# string match -r -a -n at ratatat'
|
||||
string match -r -a -n at ratatat
|
||||
|
||||
string match -r -i '0x[0-9a-f]{1,8}' 'int magic = 0xBadC0de;'
|
||||
echo
|
||||
echo '# string match -r -i "0x[0-9a-f]{1,8}" "int magic = 0xBadC0de;"'
|
||||
string match -r -i "0x[0-9a-f]{1,8}" "int magic = 0xBadC0de;"
|
||||
|
||||
string replace is was 'blue is my favorite'
|
||||
echo
|
||||
echo '# string replace is was "blue is my favorite"'
|
||||
string replace is was "blue is my favorite"
|
||||
|
||||
echo
|
||||
echo '# string replace 3rd last 1st 2nd 3rd'
|
||||
string replace 3rd last 1st 2nd 3rd
|
||||
|
||||
string replace -a ' ' _ 'spaces to underscores'
|
||||
echo
|
||||
echo '# string replace -a " " _ "spaces to underscores"'
|
||||
string replace -a " " _ "spaces to underscores"
|
||||
|
||||
string replace -r -a '[^\d.]+' ' ' '0 one two 3.14 four 5x'
|
||||
echo
|
||||
echo '# string replace -r -a "[^\d.]+" " " "0 one two 3.14 four 5x"'
|
||||
string replace -r -a "[^\d.]+" " " "0 one two 3.14 four 5x"
|
||||
|
||||
string replace -r '(\w+)\s+(\w+)' '$2 $1 $$' 'left right'
|
||||
echo
|
||||
echo '# string replace -r "(\w+)\s+(\w+)" "\$2 \$1 \$\$" "left right"'
|
||||
string replace -r "(\w+)\s+(\w+)" "\$2 \$1 \$\$" "left right"
|
||||
|
||||
string replace -r '\s*newline\s*' '\n' 'put a newline here'
|
||||
echo
|
||||
echo '# string replace -r "\s*newline\s*" "\n" "put a newline here"'
|
||||
string replace -r "\s*newline\s*" "\n" "put a newline here"
|
||||
|
||||
string replace -r -a '(\w)' '$1$1' ab
|
||||
echo
|
||||
echo '# string replace -r -a "(\w)" "\$1\$1" ab'
|
||||
string replace -r -a "(\w)" "\$1\$1" ab
|
||||
|
||||
# test some failure cases
|
||||
string match -r '[' 'a[sd' 2>/dev/null; or echo "invalid expression error"
|
||||
echo '# string match -r "[" "a[sd"' >&2
|
||||
string match -r "[" "a[sd"; and echo "unexpected exit 0" >&2
|
||||
|
||||
string invalidarg 2>/dev/null; or echo "invalid argument error"
|
||||
echo >&2
|
||||
echo '# string invalidarg' >&2
|
||||
string invalidarg; and echo "unexpected exit 0" >&2
|
||||
|
||||
string length 2>/dev/null; or echo "missing argument returns 0"
|
||||
echo
|
||||
echo '# string length'
|
||||
string length; or echo "missing argument returns 1"
|
||||
|
||||
echo
|
||||
echo '# string match -r -v "[dcantg].*" dog can cat diz'
|
||||
string match -r -v "[dcantg].*" dog can cat diz; or echo "no regexp invert match"
|
||||
|
||||
echo
|
||||
echo '# string match -v "???" dog can cat diz'
|
||||
string match -v "???" dog can cat diz; or echo "no glob invert match"
|
||||
|
||||
string match -rvn a bbb
|
||||
echo
|
||||
echo '# string match -rvn a bbb'
|
||||
string match -rvn a bbb; or echo "exit 1"
|
||||
|
||||
# test repeat subcommand
|
||||
string repeat -n 2 'foo'
|
||||
echo
|
||||
echo '# string repeat -n 2 "foo"'
|
||||
string repeat -n 2 "foo"
|
||||
|
||||
string repeat --count 2 'foo'
|
||||
echo
|
||||
echo '# string repeat --count 2 "foo"'
|
||||
string repeat --count 2 "foo"
|
||||
|
||||
echo
|
||||
echo '# echo foo | string repeat -n 2'
|
||||
echo foo | string repeat -n 2
|
||||
|
||||
string repeat -n2 -q 'foo'; and echo "exit 0"
|
||||
echo
|
||||
echo '# string repeat -n2 -q "foo"'
|
||||
string repeat -n2 -q "foo"; and echo "exit 0"
|
||||
|
||||
string repeat -n2 --quiet 'foo'; and echo "exit 0"
|
||||
echo
|
||||
echo '# string repeat -n2 --quiet "foo"'
|
||||
string repeat -n2 --quiet "foo"; and echo "exit 0"
|
||||
|
||||
string repeat -n0 'foo'; or echo "exit 1"
|
||||
echo
|
||||
echo '# string repeat -n0 "foo"'
|
||||
string repeat -n0 "foo"; or echo "exit 1"
|
||||
|
||||
echo
|
||||
echo '# string repeat -n0'
|
||||
string repeat -n0; or echo "exit 1"
|
||||
|
||||
echo
|
||||
echo '# string repeat -m0'
|
||||
string repeat -m0; or echo "exit 1"
|
||||
|
||||
string repeat -n1 -N 'there is '; echo "no newline"
|
||||
echo
|
||||
echo '# string repeat -n1 -N "there is "'
|
||||
string repeat -n1 -N "there is "; echo "no newline"
|
||||
|
||||
string repeat -n1 --no-newline 'there is '; echo "no newline"
|
||||
echo
|
||||
echo '# string repeat -n1 --no-newline "there is "'
|
||||
string repeat -n1 --no-newline "there is "; echo "no newline"
|
||||
|
||||
string repeat -n10 -m4 'foo'
|
||||
echo
|
||||
echo '# string repeat -n10 -m4 "foo"'
|
||||
string repeat -n10 -m4 "foo"
|
||||
|
||||
string repeat -n10 --max 5 'foo'
|
||||
echo
|
||||
echo '# string repeat -n10 --max 5 "foo"'
|
||||
string repeat -n10 --max 5 "foo"
|
||||
|
||||
string repeat -n3 -m20 'foo'
|
||||
echo
|
||||
echo '# string repeat -n3 -m20 "foo"'
|
||||
string repeat -n3 -m20 "foo"
|
||||
|
||||
string repeat -m4 'foo'
|
||||
echo
|
||||
echo '# string repeat -m4 "foo"'
|
||||
string repeat -m4 "foo"
|
||||
|
||||
string repeat -n-1 'foo'; or echo "exit 2"
|
||||
echo >&2
|
||||
echo '# string repeat -n-1 "foo"' >&2
|
||||
string repeat -n-1 "foo"; and echo "exit 0" >&2
|
||||
|
||||
string repeat -m-1 'foo'; or echo "exit 2"
|
||||
echo >&2
|
||||
echo '# string repeat -m-1 "foo"' >&2
|
||||
string repeat -m-1 "foo"; and echo "exit 0" >&2
|
||||
|
||||
string repeat -n notanumber 'foo'; or echo "exit 2"
|
||||
echo >&2
|
||||
echo '# string repeat -n notanumber "foo"' >&2
|
||||
string repeat -n notanumber "foo"; and echo "exit 0" >&2
|
||||
|
||||
string repeat -m notanumber 'foo'; or echo "exit 2"
|
||||
echo >&2
|
||||
echo '# string repeat -m notanumber "foo"' >&2
|
||||
string repeat -m notanumber "foo"; and echo "exit 0" >&2
|
||||
|
||||
echo 'stdin' | string repeat -n1 'and arg'; or echo "exit 2"
|
||||
echo >&2
|
||||
echo '# echo "stdin" | string repeat -n1 "and arg"' >&2
|
||||
echo "stdin" | string repeat -n1 "and arg"; and echo "exit 0" >&2
|
||||
|
||||
string repeat -n; or echo "exit 2"
|
||||
echo >&2
|
||||
echo '# string repeat -n' >&2
|
||||
string repeat -n; and echo "exit 0" >&2
|
||||
|
||||
string repeat -l fakearg 2>&1 | head -n1 1>&2
|
||||
echo >&2
|
||||
echo '# string repeat -l fakearg 2>&1' >&2
|
||||
string repeat -l fakearg
|
||||
|
||||
string repeat ''
|
||||
and echo string repeat empty string did not fail
|
||||
echo
|
||||
echo '# string repeat ""'
|
||||
string repeat ""
|
||||
or echo string repeat empty string failed
|
||||
|
||||
string repeat -n3 ''
|
||||
and echo string repeat empty string did not fail
|
||||
echo
|
||||
echo '# string repeat -n3 ""'
|
||||
string repeat -n3 ""
|
||||
or echo string repeat empty string failed
|
||||
|
||||
# Test equivalent matches with/without the --filter, --regex, and --invert flags.
|
||||
echo
|
||||
echo '# string match -f x abc dxf xyz jkx x z'
|
||||
string match -f x abc dxf xyz jkx x z
|
||||
or echo exit 1
|
||||
|
||||
echo
|
||||
echo '# string match x abc dxf xyz jkx x z'
|
||||
string match x abc dxf xyz jkx x z
|
||||
|
||||
echo
|
||||
echo '# string match --filter -r "a*b[xy]+" abc abxc bye aaabyz kaabxz abbxy abcx caabxyxz'
|
||||
string match --filter -r "a*b[xy]+" abc abxc bye aaabyz kaabxz abbxy abcx caabxyxz
|
||||
or echo exit 1
|
||||
|
||||
echo
|
||||
echo '# string match -r "a*b[xy]+" abc abxc bye aaabyz kaabxz abbxy abcx caabxyxz'
|
||||
string match -r "a*b[xy]+" abc abxc bye aaabyz kaabxz abbxy abcx caabxyxz
|
||||
or echo exit 1
|
||||
|
||||
# Make sure that groups are handled correct with/without --filter.
|
||||
echo
|
||||
echo '# string match --filter -r "a*b([xy]+)" abc abxc bye aaabyz kaabxz abbxy abcx caabxyxz'
|
||||
string match --filter -r "a*b([xy]+)" abc abxc bye aaabyz kaabxz abbxy abcx caabxyxz
|
||||
or echo exit 1
|
||||
|
||||
echo
|
||||
echo '# string match -r "a*b([xy]+)" abc abxc bye aaabyz kaabxz abbxy abcx caabxyxz'
|
||||
string match -r "a*b([xy]+)" abc abxc bye aaabyz kaabxz abbxy abcx caabxyxz
|
||||
or echo exit 1
|
||||
|
||||
exit 0
|
||||
|
|
182
tests/string.out
182
tests/string.out
|
@ -1,85 +1,247 @@
|
|||
# string match -r -v "c.*" dog can cat diz
|
||||
dog
|
||||
diz
|
||||
exit 0
|
||||
|
||||
# string match -q -r -v "c.*" dog can cat diz
|
||||
exit 0
|
||||
|
||||
# string match -v "c*" dog can cat diz
|
||||
dog
|
||||
diz
|
||||
exit 0
|
||||
|
||||
# string match -q -v "c*" dog can cat diz
|
||||
exit 0
|
||||
|
||||
# string match -v "d*" dog dan dat diz
|
||||
exit 1
|
||||
|
||||
# string match -q -v "d*" dog dan dat diz
|
||||
exit 1
|
||||
|
||||
# string match -r -v x y
|
||||
y
|
||||
exit 0
|
||||
|
||||
# string match -r -v x x
|
||||
exit 1
|
||||
|
||||
# string match -q -r -v x y
|
||||
exit 0
|
||||
|
||||
# string match -q -r -v x x
|
||||
exit 1
|
||||
|
||||
# string length "hello, world"
|
||||
12
|
||||
|
||||
# string length -q ""
|
||||
zero length
|
||||
|
||||
# string sub --length 2 abcde
|
||||
ab
|
||||
|
||||
# string sub -s 2 -l 2 abcde
|
||||
bc
|
||||
|
||||
# string sub --start=-2 abcde
|
||||
de
|
||||
|
||||
# string split . example.com
|
||||
example
|
||||
com
|
||||
|
||||
# string split -r -m1 / /usr/local/bin/fish
|
||||
/usr/local/bin
|
||||
fish
|
||||
|
||||
# string split "" abc
|
||||
a
|
||||
b
|
||||
c
|
||||
|
||||
# seq 3 | string join ...
|
||||
1...2...3
|
||||
abc
|
||||
|
||||
# string trim " abc "
|
||||
abc
|
||||
|
||||
# string trim --right --chars=yz xyzzy zany
|
||||
x
|
||||
zan
|
||||
|
||||
# echo \x07 | string escape
|
||||
\cg
|
||||
|
||||
# string match "?" a
|
||||
a
|
||||
|
||||
# string match "a*b" axxb
|
||||
axxb
|
||||
|
||||
# string match -i "a??B" Axxb
|
||||
Axxb
|
||||
|
||||
# echo "ok?" | string match "*\?"
|
||||
ok?
|
||||
|
||||
# string match -r "cat|dog|fish" "nice dog"
|
||||
dog
|
||||
|
||||
# string match -r "(\d\d?):(\d\d):(\d\d)" 2:34:56
|
||||
2:34:56
|
||||
2
|
||||
34
|
||||
56
|
||||
|
||||
# string match -r "^(\w{2,4})\g1\$" papa mud murmur
|
||||
papa
|
||||
pa
|
||||
murmur
|
||||
mur
|
||||
|
||||
# string match -r -a -n at ratatat
|
||||
2 2
|
||||
4 2
|
||||
6 2
|
||||
|
||||
# string match -r -i "0x[0-9a-f]{1,8}" "int magic = 0xBadC0de;"
|
||||
0xBadC0de
|
||||
|
||||
# string replace is was "blue is my favorite"
|
||||
blue was my favorite
|
||||
|
||||
# string replace 3rd last 1st 2nd 3rd
|
||||
1st
|
||||
2nd
|
||||
last
|
||||
|
||||
# string replace -a " " _ "spaces to underscores"
|
||||
spaces_to_underscores
|
||||
|
||||
# string replace -r -a "[^\d.]+" " " "0 one two 3.14 four 5x"
|
||||
0 3.14 5
|
||||
|
||||
# string replace -r "(\w+)\s+(\w+)" "\$2 \$1 \$\$" "left right"
|
||||
right left $
|
||||
|
||||
# string replace -r "\s*newline\s*" "\n" "put a newline here"
|
||||
put a
|
||||
here
|
||||
|
||||
# string replace -r -a "(\w)" "\$1\$1" ab
|
||||
aabb
|
||||
invalid expression error
|
||||
invalid argument error
|
||||
missing argument returns 0
|
||||
|
||||
# string length
|
||||
missing argument returns 1
|
||||
|
||||
# string match -r -v "[dcantg].*" dog can cat diz
|
||||
no regexp invert match
|
||||
|
||||
# string match -v "???" dog can cat diz
|
||||
no glob invert match
|
||||
|
||||
# string match -rvn a bbb
|
||||
1 3
|
||||
|
||||
# string repeat -n 2 "foo"
|
||||
foofoo
|
||||
|
||||
# string repeat --count 2 "foo"
|
||||
foofoo
|
||||
|
||||
# echo foo | string repeat -n 2
|
||||
foofoo
|
||||
|
||||
# string repeat -n2 -q "foo"
|
||||
exit 0
|
||||
|
||||
# string repeat -n2 --quiet "foo"
|
||||
exit 0
|
||||
|
||||
# string repeat -n0 "foo"
|
||||
exit 1
|
||||
|
||||
# string repeat -n0
|
||||
exit 1
|
||||
|
||||
# string repeat -m0
|
||||
exit 1
|
||||
|
||||
# string repeat -n1 -N "there is "
|
||||
there is no newline
|
||||
|
||||
# string repeat -n1 --no-newline "there is "
|
||||
there is no newline
|
||||
|
||||
# string repeat -n10 -m4 "foo"
|
||||
foof
|
||||
|
||||
# string repeat -n10 --max 5 "foo"
|
||||
foofo
|
||||
|
||||
# string repeat -n3 -m20 "foo"
|
||||
foofoofoo
|
||||
|
||||
# string repeat -m4 "foo"
|
||||
foof
|
||||
exit 2
|
||||
exit 2
|
||||
exit 2
|
||||
exit 2
|
||||
exit 2
|
||||
exit 2
|
||||
|
||||
# string repeat ""
|
||||
string repeat empty string failed
|
||||
|
||||
# string repeat -n3 ""
|
||||
string repeat empty string failed
|
||||
|
||||
# string match -f x abc dxf xyz jkx x z
|
||||
dxf
|
||||
xyz
|
||||
jkx
|
||||
x
|
||||
|
||||
# string match x abc dxf xyz jkx x z
|
||||
x
|
||||
|
||||
# string match --filter -r "a*b[xy]+" abc abxc bye aaabyz kaabxz abbxy abcx caabxyxz
|
||||
abxc
|
||||
bye
|
||||
aaabyz
|
||||
kaabxz
|
||||
abbxy
|
||||
caabxyxz
|
||||
|
||||
# string match -r "a*b[xy]+" abc abxc bye aaabyz kaabxz abbxy abcx caabxyxz
|
||||
abx
|
||||
by
|
||||
aaaby
|
||||
aabx
|
||||
bxy
|
||||
aabxyx
|
||||
|
||||
# string match --filter -r "a*b([xy]+)" abc abxc bye aaabyz kaabxz abbxy abcx caabxyxz
|
||||
abxc
|
||||
x
|
||||
bye
|
||||
y
|
||||
aaabyz
|
||||
y
|
||||
kaabxz
|
||||
x
|
||||
abbxy
|
||||
xy
|
||||
caabxyxz
|
||||
xyx
|
||||
|
||||
# string match -r "a*b([xy]+)" abc abxc bye aaabyz kaabxz abbxy abcx caabxyxz
|
||||
abx
|
||||
x
|
||||
by
|
||||
y
|
||||
aaaby
|
||||
y
|
||||
aabx
|
||||
x
|
||||
bxy
|
||||
xy
|
||||
aabxyx
|
||||
xyx
|
||||
|
|
Loading…
Reference in a new issue