1
0
Fork 0
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:
Peter Stephenson 2010-02-27 00:18:13 +00:00
parent 31123a1184
commit 21193d7f01
4 changed files with 73 additions and 14 deletions

View file

@ -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 $
*****************************************************

View file

@ -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

View file

@ -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;

View file

@ -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