mirror of
git://git.code.sf.net/p/zsh/code
synced 2025-05-22 00:11:30 +02:00
52202: improve handling of quoting in ${var/pattern/replacement}
This commit is contained in:
parent
be223aedee
commit
e6ad117ccb
4 changed files with 49 additions and 25 deletions
|
@ -1,3 +1,9 @@
|
|||
2023-11-15 Bart Schaefer <schaefer@zsh.org>
|
||||
|
||||
* 52202: Src/lex.c, Src/subst.c, Test/D04parameter.ztst: improve
|
||||
handling of quoting in ${var/pattern/replacement}. Still not
|
||||
perfect, e.g., deeply nested expansions in the pattern may fail.
|
||||
|
||||
2023-11-14 Oliver Kiddle <opk@zsh.org>
|
||||
|
||||
* github #106: Matt Koscica: Completion/Unix/Command/_tmux,
|
||||
|
|
53
Src/lex.c
53
Src/lex.c
|
@ -938,7 +938,7 @@ gettokstr(int c, int sub)
|
|||
{
|
||||
int bct = 0, pct = 0, brct = 0, seen_brct = 0, fdpar = 0;
|
||||
int intpos = 1, in_brace_param = 0, cmdsubst = 0;
|
||||
int inquote, unmatched = 0;
|
||||
int inquote, unmatched = 0, in_pattern = 0;
|
||||
enum lextok peek;
|
||||
#ifdef DEBUG
|
||||
int ocmdsp = cmdsp;
|
||||
|
@ -1160,7 +1160,7 @@ gettokstr(int c, int sub)
|
|||
if (bct-- == in_brace_param) {
|
||||
if (cmdsubst)
|
||||
cmdpop();
|
||||
in_brace_param = cmdsubst = 0;
|
||||
in_brace_param = cmdsubst = in_pattern = 0;
|
||||
}
|
||||
c = Outbrace;
|
||||
break;
|
||||
|
@ -1309,7 +1309,8 @@ gettokstr(int c, int sub)
|
|||
lexbuf.ptr--, lexbuf.len--;
|
||||
else
|
||||
break;
|
||||
}
|
||||
} else if (in_pattern && c == '/')
|
||||
add(Bnull);
|
||||
add(c);
|
||||
}
|
||||
ALLOWHIST
|
||||
|
@ -1397,26 +1398,36 @@ gettokstr(int c, int sub)
|
|||
*/
|
||||
c = Dash;
|
||||
break;
|
||||
case LX2_BANG:
|
||||
/*
|
||||
* Same logic as Dash, for ! to perform negation in range.
|
||||
*/
|
||||
if (seen_brct)
|
||||
c = Bang;
|
||||
else
|
||||
c = '!';
|
||||
}
|
||||
add(c);
|
||||
c = hgetc();
|
||||
if (intpos)
|
||||
case LX2_BANG:
|
||||
/*
|
||||
* Same logic as Dash, for ! to perform negation in range.
|
||||
*/
|
||||
if (seen_brct)
|
||||
c = Bang;
|
||||
else
|
||||
c = '!';
|
||||
case LX2_OTHER:
|
||||
if (in_brace_param) {
|
||||
if (c == '/') {
|
||||
if (in_pattern == 0)
|
||||
in_pattern = 2;
|
||||
else
|
||||
--in_pattern;
|
||||
}
|
||||
}
|
||||
}
|
||||
add(c);
|
||||
c = hgetc();
|
||||
if (intpos)
|
||||
intpos--;
|
||||
if (lexstop)
|
||||
if (lexstop)
|
||||
break;
|
||||
if (!cmdsubst && in_brace_param && act == LX2_STRING &&
|
||||
(c == '|' || c == Bar || inblank(c))) {
|
||||
cmdsubst = in_brace_param;
|
||||
cmdpush(CS_CURSH);
|
||||
}
|
||||
if (!cmdsubst && in_brace_param && act == LX2_STRING &&
|
||||
(c == '|' || c == Bar || inblank(c))) {
|
||||
cmdsubst = in_brace_param;
|
||||
cmdpush(CS_CURSH);
|
||||
} else if (in_pattern == 2 && c != '/')
|
||||
in_pattern = 1;
|
||||
}
|
||||
brk:
|
||||
if (errflag) {
|
||||
|
|
|
@ -3088,6 +3088,13 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int pf_flags,
|
|||
chuck(ptr);
|
||||
else
|
||||
ptr++;
|
||||
} else if (c == Dnull) {
|
||||
chuck(ptr);
|
||||
while (*ptr && *ptr != c)
|
||||
ptr++;
|
||||
if (*ptr == Dnull)
|
||||
chuck(ptr);
|
||||
ptr--; /* Outer loop is about to increment */
|
||||
}
|
||||
}
|
||||
replstr = (*ptr && ptr[1]) ? ptr+1 : "";
|
||||
|
|
|
@ -2762,13 +2762,13 @@ F:behavior, see http://austingroupbugs.net/view.php?id=888
|
|||
|
||||
slash='/'
|
||||
print -r -- x${slash/'/'}y
|
||||
-Df:(users/28784) substituting a single-quoted backslash, part #1: slash
|
||||
0:(users/28784) substituting a single-quoted backslash, part #1: slash
|
||||
>xy
|
||||
|
||||
single_quote="'"
|
||||
print -r -- x${single_quote/'/'}y
|
||||
-Df:(users/28784) substituting a single-quoted backslash, part #2: single quote
|
||||
>x/y
|
||||
print -r -- x${single_quote/$'/'}y
|
||||
0:(users/28784) substituting a single-quoted backslash, part #2: single quote
|
||||
>x'y
|
||||
|
||||
control="foobar"
|
||||
print -r -- x${control/'bar'}y
|
||||
|
|
Loading…
Reference in a new issue