diff options
author | Tanaka Akira <akr@users.sourceforge.net> | 1999-08-30 10:17:30 +0000 |
---|---|---|
committer | Tanaka Akira <akr@users.sourceforge.net> | 1999-08-30 10:17:30 +0000 |
commit | 5e1dc5dc013a510fdb971566dab86f4987419cac (patch) | |
tree | 4dbe8a1069224b603703acf2adf927f193245689 | |
parent | ffa18a29ab864c60153601616053e0e3158235e9 (diff) | |
download | zsh-5e1dc5dc013a510fdb971566dab86f4987419cac.tar.gz zsh-5e1dc5dc013a510fdb971566dab86f4987419cac.tar.xz zsh-5e1dc5dc013a510fdb971566dab86f4987419cac.zip |
zsh-workers/7540
-rw-r--r-- | Doc/Zsh/expn.yo | 15 | ||||
-rw-r--r-- | Src/subst.c | 122 |
2 files changed, 118 insertions, 19 deletions
diff --git a/Doc/Zsh/expn.yo b/Doc/Zsh/expn.yo index b9af9b83f..cafd1feaa 100644 --- a/Doc/Zsh/expn.yo +++ b/Doc/Zsh/expn.yo @@ -447,6 +447,21 @@ match for tt(t*e) is substituted and the result is `tt(spy star)', while in the second case, the shortest matches are taken and the result is `tt(spy spy lispy star)'. ) +xitem(tt(${)var(name)tt(^)var(pattern)tt(^)var(then)tt(^)var(else)tt(})) +item(tt(${)var(name)tt(^^)var(pattern)tt(^)var(then)tt(^)var(else)tt(}))( +If the expansion of var(name) matches the var(pattern), the var(then) +string is substituted, otherwise the var(else) string is +substituted. In the second form the var(pattern) is taken to be +negated (even if the tt(EXTENDED_GLOB) option is not set. The +var(else) string with the preceding `tt(^)' may be omitted in which +case the expansion behaves as if var(name) were unset (or, if +var(name) is an array, as if the element compared did not exist). In +the var(pattern) and the var(then) string a `tt(^)' may be included by +preceding it with two backslashes. Finally, the var(then) and +var(else) string may consist of only a dot to make it expand to the +original string. To make them expand to only a dot, the string +`tt(\.)' has to be used. +) item(tt(${#)var(spec)tt(}))( If var(spec) is one of the above substitutions, substitute the length in characters of the result instead of diff --git a/Src/subst.c b/Src/subst.c index 7619c94a9..a3853472c 100644 --- a/Src/subst.c +++ b/Src/subst.c @@ -725,6 +725,8 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int ssub) char *sep = NULL, *spsep = NULL; char *premul = NULL, *postmul = NULL, *preone = NULL, *postone = NULL; char *replstr = NULL; /* replacement string for /orig/repl */ + char *thenstr, *elsestr; /* then and else for ${..^..^..^..} */ + int negpat = 0; zlong prenum = 0, postnum = 0; int copied = 0; int arrasg = 0; @@ -1227,7 +1229,8 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int ssub) *s == '%' || *s == '#' || *s == Pound || *s == '?' || *s == Quest || - *s == '/')) { + *s == '/' || + *s == '^' || *s == Hat)) { if (!flnum) flnum++; @@ -1282,7 +1285,47 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int ssub) untokenize(replstr); *ptr = '\0'; } + if (s[-1] == '^' || s[-1] == Hat) { + char *ptr = s; + if (*s == s[-1]) { + s++; + negpat = 1; + } + for (ptr = s; *ptr && *ptr != '^' && *ptr != Hat; ptr++) + if (*ptr == '\\' && (ptr[1] == '^' || ptr[1] == Hat)) + chuck(ptr); + if (!*ptr || !ptr[1]) { + zerr("missing `then' string", NULL, 0); + return NULL; + } + *ptr++ = '\0'; + thenstr = ptr; + for (; *ptr && *ptr != '^' && *ptr != Hat; ptr++) + if (*ptr == '\\' && (ptr[1] == '^' || ptr[1] == Hat)) + chuck(ptr); + if (*ptr) { + elsestr = ptr + 1; + if (elsestr[0] == '\\' && elsestr[1] == '.') + elsestr++; + if (elsestr[0] == '.' && !elsestr[1]) + elsestr = (char *) 1; + else { + singsub(&elsestr); + untokenize(elsestr); + } + *ptr = '\0'; + } else + elsestr = NULL; + if (thenstr[0] == '\\' && thenstr[1] == '.') + thenstr++; + if (thenstr[0] == '.' && !thenstr[1]) + thenstr = (char *) 1; + else { + singsub(&thenstr); + untokenize(thenstr); + } + } if (colf) flags |= SUB_ALL; /* @@ -1396,6 +1439,8 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int ssub) case '#': case Pound: case '/': + case '^': + case Hat: if (qt) { int one = noerrs, oef = errflag, haserr; @@ -1417,27 +1462,66 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int ssub) char t = s[-1]; singsub(&s); - if (t == '/' && (flags & SUB_SUBSTR)) { - if (*s == '#' || *s == '%') { - flags &= ~SUB_SUBSTR; - if (*s == '%') - flags |= SUB_END; - s++; - } else if (*s == '\\') { - s++; + if (t == '^' || t == Hat) { + if (!vunset && isarr) { + char **ap, **pp; + Patprog pprg; + + if (!(pprg = patcompile(s, PAT_STATIC, NULL))) { + zerr("bad pattern: %s", s, 0); + return NULL; + } + if (!copied) + aval = arrdup(aval), copied = 1; + for (ap = pp = aval; *ap; ap++) { + if ((!!pattry(pprg, *ap)) ^ negpat) + *pp++ = dupstring(thenstr == ((char *) 1) ? + *ap : thenstr); + else if (elsestr) + *pp++ = dupstring(elsestr == ((char *) 1) ? + *ap : elsestr); + } + *pp = NULL; + } else { + Patprog pprg; + + if (vunset) + val = dupstring(""); + if ((pprg = patcompile(s, PAT_STATIC, NULL)) && + ((!!pattry(pprg, val)) ^ negpat)) + val = dupstring(thenstr == ((char *) 1) ? + val : thenstr); + else if (elsestr) + val = dupstring(elsestr == ((char *) 1) ? + val : elsestr); + else { + vunset = 1; + val = dupstring(""); + } + copied = 1; + } + } else { + if (t == '/' && (flags & SUB_SUBSTR)) { + if (*s == '#' || *s == '%') { + flags &= ~SUB_SUBSTR; + if (*s == '%') + flags |= SUB_END; + s++; + } else if (*s == '\\') { + s++; + } + } + if (!vunset && isarr) { + getmatcharr(&aval, s, flags, flnum, replstr); + copied = 1; + } else { + if (vunset) + val = dupstring(""); + getmatch(&val, s, flags, flnum, replstr); + copied = 1; } } } - - if (!vunset && isarr) { - getmatcharr(&aval, s, flags, flnum, replstr); - copied = 1; - } else { - if (vunset) - val = dupstring(""); - getmatch(&val, s, flags, flnum, replstr); - copied = 1; - } break; } } else { /* no ${...=...} or anything, but possible modifiers. */ |