mirror of
git://git.code.sf.net/p/zsh/code
synced 2025-11-01 18:30:55 +01:00
users/14905 + 14906: problems with :s in parameter expansion
This commit is contained in:
parent
31123a1184
commit
21193d7f01
4 changed files with 73 additions and 14 deletions
|
|
@ -1,3 +1,9 @@
|
|||
2010-02-27 Peter Stephenson <p.w.stephenson@ntlworld.com>
|
||||
|
||||
* users/14905 (modified, see users/14096): Doc/Zsh/expn.yo,
|
||||
Src/subst.c, Test/D04parameter.ztst: fix various problems
|
||||
with :s modifier in parameters.
|
||||
|
||||
2010-02-26 Peter Stephenson <pws@csr.com>
|
||||
|
||||
* users/14902: Src/Modules/datetime.c: another go.
|
||||
|
|
@ -12843,5 +12849,5 @@
|
|||
|
||||
*****************************************************
|
||||
* This is used by the shell to define $ZSH_PATCHLEVEL
|
||||
* $Revision: 1.4920 $
|
||||
* $Revision: 1.4921 $
|
||||
*****************************************************
|
||||
|
|
|
|||
|
|
@ -273,6 +273,8 @@ The forms `tt(gs/)var(l)tt(/)var(r)' and `tt(s/)var(l)tt(/)var(r)tt(/:G)'
|
|||
perform global substitution, i.e. substitute every occurrence of var(r)
|
||||
for var(l). Note that the tt(g) or tt(:G) must appear in exactly the
|
||||
position shown.
|
||||
|
||||
See further notes on this form of substitution below.
|
||||
)
|
||||
item(tt(&))(
|
||||
Repeat the previous tt(s) substitution. Like tt(s), may be preceded
|
||||
|
|
@ -293,18 +295,18 @@ parameter expansion.
|
|||
)
|
||||
enditem()
|
||||
|
||||
The tt(s/l/r/) substitution works as follows. By default the left-hand
|
||||
side of substitutions are not patterns, but character strings. Any
|
||||
character can be used as the delimiter in place of `tt(/)'. A
|
||||
backslash quotes the delimiter character. The character `tt(&)', in
|
||||
the right-hand-side var(r), is replaced by the text from the
|
||||
The tt(s/)var(l)tt(/)var(r)tt(/) substitution works as follows. By
|
||||
default the left-hand side of substitutions are not patterns, but
|
||||
character strings. Any character can be used as the delimiter in place
|
||||
of `tt(/)'. A backslash quotes the delimiter character. The character
|
||||
`tt(&)', in the right-hand-side var(r), is replaced by the text from the
|
||||
left-hand-side var(l). The `tt(&)' can be quoted with a backslash. A
|
||||
null var(l) uses the previous string either from the previous var(l)
|
||||
or from the contextual scan string var(s) from `tt(!?)var(s)'. You can
|
||||
null var(l) uses the previous string either from the previous var(l) or
|
||||
from the contextual scan string var(s) from `tt(!?)var(s)'. You can
|
||||
omit the rightmost delimiter if a newline immediately follows var(r);
|
||||
the rightmost `tt(?)' in a context scan can similarly be omitted.
|
||||
Note the same record of the last var(l) and var(r) is maintained
|
||||
across all forms of expansion.
|
||||
the rightmost `tt(?)' in a context scan can similarly be omitted. Note
|
||||
the same record of the last var(l) and var(r) is maintained across all
|
||||
forms of expansion.
|
||||
|
||||
If the option tt(HIST_SUBST_PATTERN) is set, var(l) is treated as
|
||||
a pattern of the usual form described in
|
||||
|
|
|
|||
31
Src/subst.c
31
Src/subst.c
|
|
@ -3282,6 +3282,13 @@ modify(char **str, char **ptr)
|
|||
ptr1 += charlen;
|
||||
for (ptr2 = ptr1, charlen = 0; *ptr2; ptr2 += charlen) {
|
||||
convchar_t del2;
|
||||
if ((*ptr2 == Bnull || *ptr2 == '\\') && ptr2[1]) {
|
||||
/* in double quotes, the backslash isn't tokenized */
|
||||
if (*ptr2 == '\\')
|
||||
*ptr2 = Bnull;
|
||||
charlen = 2;
|
||||
continue;
|
||||
}
|
||||
charlen = MB_METACHARLENCONV(ptr2, &del2);
|
||||
#ifdef MULTIBYTE_SUPPORT
|
||||
if (del2 == WEOF)
|
||||
|
|
@ -3301,6 +3308,13 @@ modify(char **str, char **ptr)
|
|||
*ptr1end = '\0';
|
||||
for (ptr3 = ptr2, charlen = 0; *ptr3; ptr3 += charlen) {
|
||||
convchar_t del3;
|
||||
if ((*ptr3 == Bnull || *ptr3 == '\\') && ptr3[1]) {
|
||||
/* in double quotes, the backslash isn't tokenized */
|
||||
if (*ptr3 == '\\')
|
||||
*ptr3 = Bnull;
|
||||
charlen = 2;
|
||||
continue;
|
||||
}
|
||||
charlen = MB_METACHARLENCONV(ptr3, &del3);
|
||||
#ifdef MULTIBYTE_SUPPORT
|
||||
if (del3 == WEOF)
|
||||
|
|
@ -3326,9 +3340,20 @@ modify(char **str, char **ptr)
|
|||
chuck(tt--);
|
||||
if (!isset(HISTSUBSTPATTERN))
|
||||
untokenize(hsubl);
|
||||
for (tt = hsubr = ztrdup(ptr2); *tt; tt++)
|
||||
if (inull(*tt) && *tt != Bnullkeep)
|
||||
chuck(tt--);
|
||||
for (tt = hsubr = ztrdup(ptr2); *tt; tt++) {
|
||||
if (inull(*tt) && *tt != Bnullkeep) {
|
||||
if (*tt == Bnull && (tt[1] == '&' || tt[1] == '\\')) {
|
||||
/*
|
||||
* The substitution will treat \& and \\
|
||||
* specially. We need to leave real \'s
|
||||
* as the first character for this to work.
|
||||
*/
|
||||
*tt = '\\';
|
||||
} else {
|
||||
chuck(tt--);
|
||||
}
|
||||
}
|
||||
}
|
||||
*ptr1end = sav1;
|
||||
*ptr3 = sav;
|
||||
*ptr = ptr3 - 1;
|
||||
|
|
|
|||
|
|
@ -947,6 +947,32 @@
|
|||
>/
|
||||
>/
|
||||
|
||||
baz=foo/bar
|
||||
zab=oof+rab
|
||||
print ${baz:s/\//+/}
|
||||
print "${baz:s/\//+/}"
|
||||
print ${zab:s/+/\//}
|
||||
print "${zab:s/+/\//}"
|
||||
0:Quoting of separator in substitution modifier
|
||||
>foo+bar
|
||||
>foo+bar
|
||||
>oof/rab
|
||||
>oof/rab
|
||||
|
||||
print -r ${${:-one/two}:s,/,X&Y,}
|
||||
print -r ${${:-one/two}:s,/,X\&Y,}
|
||||
print -r ${${:-one/two}:s,/,X\\&Y,}
|
||||
print -r "${${:-one/two}:s,/,X&Y,}"
|
||||
print -r "${${:-one/two}:s,/,X\&Y,}"
|
||||
print -r "${${:-one/two}:s,/,X\\&Y,}"
|
||||
0:Quoting of ampersand in substitution modifier RHS
|
||||
>oneX/Ytwo
|
||||
>oneX&Ytwo
|
||||
>oneX\/Ytwo
|
||||
>oneX/Ytwo
|
||||
>oneX&Ytwo
|
||||
>oneX\/Ytwo
|
||||
|
||||
nully=($'a\0c' $'a\0b\0b' $'a\0b\0a' $'a\0b\0' $'a\0b' $'a\0' $'a')
|
||||
for string in ${(o)nully}; do
|
||||
for (( i = 1; i <= ${#string}; i++ )); do
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue