Reputation: 531798
According to man zshexpn
(5.0.2):
~ Force string arguments to any of the flags below that follow within the parentheses to be treated as patterns.
For example, using the s
flag to perform field splitting requires a string argument:
% print -l ${(s:9:):-"foo893bar923baz"}
foo8
3bar
23baz
My reading of the ~
flag suggests that I should be able to specify a pattern in place of a literal string to split on, so that the following
% print -l ${(~s:<->:):-"foo893bar923baz"}
should produce
foo
bar
baz
Instead, it behaves the same as if I omit the ~
, performing no splitting at all.
% print -l ${(s:<->:):-"foo893bar923baz"}
foo893bar923baz
% print -l ${(~s:<->:):-"foo893bar923baz"}
foo893bar923baz
Upvotes: -1
Views: 464
Reputation: 1700
Ok, rereading the question, it's the difference between this:
$ val="foo???bar???baz"
$ print -l ${(s.?.)val}
foo
bar
baz
And this:
$ val="foo???bar???baz"
$ print -l ${(~s.?.)val}
foo???bar???baz
It operates on the variable, i.e. the "argument" to the split (from your documentation quote). In the first example, we substitute literal ?
, and in the second, we treat the variable as a glob, and there are no literal ?
, so nothing gets substituted.
Still, though, split works on characters and not globs in the substution itself, from the documentation:
s:string:
Force field splitting (see the option SH_WORD_SPLIT) at the separator string.
So, it doesn't look like you can split on a pattern. The ~
character modifies the interpretation of the string to be split.
Also, from the same pattern expansion documentation you reference, it continutes:
Compare with a ~ outside parentheses, which forces the entire substituted string to be treated as a pattern.
[[ "?" = ${(~j.|.)array} ]]
with the EXTENDED_GLOB option set succeeds if and only if $array contains the string ‘?’ as an element. The argument may be repeated to toggle the behaviour; its effect only lasts to the end of the parenthesised group.
The difference between ${(~j.|.)array}
and ${(j.|.)~array}
is that the former treats the values inarray
as global, and the latter treats the result as a glob.
See also:
${~spec}
Turn on the GLOB_SUBST option for the evaluation of spec; if the ‘~’ is doubled, turn it off. When this option is set, the string resulting from the expansion will be interpreted as a pattern anywhere that is possible, such as in filename expansion and filename generation and pattern-matching contexts like the right hand side of the ‘=’ and ‘!=’ operators in conditions.
Here is a demo that shows the differences:
$ array=("foo???bar???baz" "foo???bar???buz")
$ [[ "foo___bar___baz" = ${(~j.|.)array} ]] && echo true || echo false
false
$ [[ "foo___bar___baz" = ${(j.|.)~array} ]] && echo true || echo false
true
And for completeness:
$ [[ "foo___bar___baz" = ${(~j.|.)~array} ]] && echo true || echo false
true
Upvotes: 2