mirror of
git://git.code.sf.net/p/zsh/code
synced 2025-09-02 22:11:54 +02:00
29224: Support negative LEN in ${VAR:OFFSET:LEN} like bash.
This commit is contained in:
parent
6a29bc80d0
commit
0198b8423d
5 changed files with 61 additions and 14 deletions
|
@ -1,3 +1,7 @@
|
|||
2011-05-19 Mikael Magnusson <mikachu@gmail.com>
|
||||
|
||||
* 29224: Support negative LEN in ${VAR:OFFSET:LEN} like bash.
|
||||
|
||||
2011-05-19 Mikael Magnusson <mikachu@gmail.com>
|
||||
|
||||
* 29261: Add g:: parameter expansion flag. Add note that s::
|
||||
|
@ -14757,5 +14761,5 @@
|
|||
|
||||
*****************************************************
|
||||
* This is used by the shell to define $ZSH_PATCHLEVEL
|
||||
* $Revision: 1.5313 $
|
||||
* $Revision: 1.5314 $
|
||||
*****************************************************
|
||||
|
|
|
@ -588,7 +588,7 @@ remove the non-matched elements).
|
|||
xitem(tt(${)var(name)tt(:)var(offset)tt(}))
|
||||
item(tt(${)var(name)tt(:)var(offset)tt(:)var(length)tt(}))(
|
||||
This syntax gives effects similar to parameter subscripting
|
||||
in the form tt($)var(name)tt({)var(start)tt(,)var(end)tt(}), but is
|
||||
in the form tt($)var(name)tt([)var(start)tt(,)var(end)tt(]), but is
|
||||
compatible with other shells; note that both var(offset) and var(length)
|
||||
are interpreted differently from the components of a subscript.
|
||||
|
||||
|
@ -608,8 +608,12 @@ the option tt(KSH_ARRAYS).
|
|||
A negative offset counts backwards from the end of the scalar or array,
|
||||
so that -1 corresponds to the last character or element, and so on.
|
||||
|
||||
var(length) is always treated directly as a length and hence may not be
|
||||
negative. The option tt(MULTIBYTE) is obeyed, i.e. the offset and length
|
||||
When positive, var(length) counts from the var(offset) position
|
||||
toward the end of the scalar or array. When negative, var(length)
|
||||
counts back from the end. If this results in a position smaller
|
||||
than var(offset), a diagnostic is printed and nothing is substituted.
|
||||
|
||||
The option tt(MULTIBYTE) is obeyed, i.e. the offset and length
|
||||
count multibyte characters where appropriate.
|
||||
|
||||
var(offset) and var(length) undergo the same set of shell substitutions
|
||||
|
@ -635,7 +639,7 @@ tt(${)var(name)tt(:-)var(word)tt(}) form of substitution. Instead, a space
|
|||
may be inserted before the tt(-). Furthermore, neither var(offset) nor
|
||||
var(length) may begin with an alphabetic character or tt(&) as these are
|
||||
used to indicate history-style modifiers. To substitute a value from a
|
||||
variable, the recommended approach is to proceed it with a tt($) as this
|
||||
variable, the recommended approach is to precede it with a tt($) as this
|
||||
signifies the intention (parameter substitution can easily be rendered
|
||||
unreadable); however, as arithmetic substitution is performed, the
|
||||
expression tt(${var: offs}) does work, retrieving the offset from
|
||||
|
|
3
NEWS
3
NEWS
|
@ -19,6 +19,9 @@ the command line is edited.
|
|||
In POSIX emulation ("emulate sh") the shell is more accurate about
|
||||
when it should or should not exit on errors.
|
||||
|
||||
The ${NAME:OFFSET:LENGTH} syntax now supports negative LENGTH, which
|
||||
counts back from the end of the string.
|
||||
|
||||
Changes between versions 4.3.10 and 4.3.11
|
||||
------------------------------------------
|
||||
|
||||
|
|
40
Src/subst.c
40
Src/subst.c
|
@ -2839,7 +2839,8 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int ssub)
|
|||
char *check_offset = check_colon_subscript(s, &check_offset2);
|
||||
if (check_offset) {
|
||||
zlong offset = mathevali(check_offset);
|
||||
zlong length = (zlong)-1;
|
||||
zlong length;
|
||||
int length_set = 0;
|
||||
int offset_hack_argzero = 0;
|
||||
if (errflag)
|
||||
return NULL;
|
||||
|
@ -2854,14 +2855,11 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int ssub)
|
|||
zerr("invalid length: %s", check_offset);
|
||||
return NULL;
|
||||
}
|
||||
if (check_offset) {
|
||||
if (check_offset) {
|
||||
length = mathevali(check_offset);
|
||||
length_set = 1;
|
||||
if (errflag)
|
||||
return NULL;
|
||||
if (length < (zlong)0) {
|
||||
zerr("invalid length: %s", check_offset);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (horrible_offset_hack) {
|
||||
|
@ -2889,8 +2887,16 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int ssub)
|
|||
}
|
||||
if (offset_hack_argzero)
|
||||
alen++;
|
||||
if (length < 0)
|
||||
length = alen;
|
||||
if (length_set) {
|
||||
if (length < 0)
|
||||
length += alen - offset;
|
||||
if (length < 0) {
|
||||
zerr("substring expression: %d < %d",
|
||||
length + offset, offset);
|
||||
return NULL;
|
||||
}
|
||||
} else
|
||||
length = alen;
|
||||
if (offset > alen)
|
||||
offset = alen;
|
||||
if (offset + length > alen)
|
||||
|
@ -2909,6 +2915,7 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int ssub)
|
|||
aval = newarr;
|
||||
} else {
|
||||
char *sptr, *eptr;
|
||||
int given_offset;
|
||||
if (offset < 0) {
|
||||
MB_METACHARINIT();
|
||||
for (sptr = val; *sptr; ) {
|
||||
|
@ -2918,12 +2925,27 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int ssub)
|
|||
if (offset < 0)
|
||||
offset = 0;
|
||||
}
|
||||
given_offset = offset;
|
||||
MB_METACHARINIT();
|
||||
if (length_set && length < 0)
|
||||
length -= offset;
|
||||
for (sptr = val; *sptr && offset; ) {
|
||||
sptr += MB_METACHARLEN(sptr);
|
||||
offset--;
|
||||
}
|
||||
if (length >= 0) {
|
||||
if (length_set) {
|
||||
if (length < 0) {
|
||||
MB_METACHARINIT();
|
||||
for (eptr = val; *eptr; ) {
|
||||
eptr += MB_METACHARLEN(eptr);
|
||||
length++;
|
||||
}
|
||||
if (length < 0) {
|
||||
zerr("substring expression: %d < %d",
|
||||
length + given_offset, given_offset);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
for (eptr = sptr; *eptr && length; ) {
|
||||
eptr += MB_METACHARLEN(eptr);
|
||||
length--;
|
||||
|
|
|
@ -1366,6 +1366,7 @@
|
|||
print ${foo:$(echo 3 + 3):`echo 4 - 3`}
|
||||
print ${foo: -1}
|
||||
print ${foo: -10}
|
||||
print ${foo:5:-2}
|
||||
0:Bash-style offsets, scalar
|
||||
>456789
|
||||
>56789
|
||||
|
@ -1377,6 +1378,7 @@
|
|||
>7
|
||||
>9
|
||||
>123456789
|
||||
>67
|
||||
|
||||
foo=(1 2 3 4 5 6 7 8 9)
|
||||
print ${foo:3}
|
||||
|
@ -1389,6 +1391,7 @@
|
|||
print ${foo:$(echo 3 + 3):`echo 4 - 3`}
|
||||
print ${foo: -1}
|
||||
print ${foo: -10}
|
||||
print ${foo:5:-2}
|
||||
0:Bash-style offsets, array
|
||||
>4 5 6 7 8 9
|
||||
>5 6 7 8 9
|
||||
|
@ -1400,6 +1403,7 @@
|
|||
>7
|
||||
>9
|
||||
>1 2 3 4 5 6 7 8 9
|
||||
>6 7
|
||||
|
||||
testfn() {
|
||||
emulate -L sh
|
||||
|
@ -1438,3 +1442,13 @@
|
|||
print ${str:0:}
|
||||
1:Regression test for missing length after offset
|
||||
?(eval):2: unrecognized modifier
|
||||
|
||||
foo="123456789"
|
||||
print ${foo:5:-6}
|
||||
1:Regression test for total length < 0 in string
|
||||
?(eval):2: substring expression: 3 < 5
|
||||
|
||||
foo=(1 2 3 4 5 6 7 8 9)
|
||||
print ${foo:5:-6}
|
||||
1:Regression test for total length < 0 in array
|
||||
?(eval):2: substring expression: 3 < 5
|
||||
|
|
Loading…
Reference in a new issue