mirror of
git://git.code.sf.net/p/zsh/code
synced 2025-09-06 11:21:22 +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>
|
2011-05-19 Mikael Magnusson <mikachu@gmail.com>
|
||||||
|
|
||||||
* 29261: Add g:: parameter expansion flag. Add note that s::
|
* 29261: Add g:: parameter expansion flag. Add note that s::
|
||||||
|
@ -14757,5 +14761,5 @@
|
||||||
|
|
||||||
*****************************************************
|
*****************************************************
|
||||||
* This is used by the shell to define $ZSH_PATCHLEVEL
|
* 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(}))
|
xitem(tt(${)var(name)tt(:)var(offset)tt(}))
|
||||||
item(tt(${)var(name)tt(:)var(offset)tt(:)var(length)tt(}))(
|
item(tt(${)var(name)tt(:)var(offset)tt(:)var(length)tt(}))(
|
||||||
This syntax gives effects similar to parameter subscripting
|
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)
|
compatible with other shells; note that both var(offset) and var(length)
|
||||||
are interpreted differently from the components of a subscript.
|
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,
|
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.
|
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
|
When positive, var(length) counts from the var(offset) position
|
||||||
negative. The option tt(MULTIBYTE) is obeyed, i.e. the offset and length
|
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.
|
count multibyte characters where appropriate.
|
||||||
|
|
||||||
var(offset) and var(length) undergo the same set of shell substitutions
|
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
|
may be inserted before the tt(-). Furthermore, neither var(offset) nor
|
||||||
var(length) may begin with an alphabetic character or tt(&) as these are
|
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
|
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
|
signifies the intention (parameter substitution can easily be rendered
|
||||||
unreadable); however, as arithmetic substitution is performed, the
|
unreadable); however, as arithmetic substitution is performed, the
|
||||||
expression tt(${var: offs}) does work, retrieving the offset from
|
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
|
In POSIX emulation ("emulate sh") the shell is more accurate about
|
||||||
when it should or should not exit on errors.
|
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
|
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);
|
char *check_offset = check_colon_subscript(s, &check_offset2);
|
||||||
if (check_offset) {
|
if (check_offset) {
|
||||||
zlong offset = mathevali(check_offset);
|
zlong offset = mathevali(check_offset);
|
||||||
zlong length = (zlong)-1;
|
zlong length;
|
||||||
|
int length_set = 0;
|
||||||
int offset_hack_argzero = 0;
|
int offset_hack_argzero = 0;
|
||||||
if (errflag)
|
if (errflag)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -2854,14 +2855,11 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int ssub)
|
||||||
zerr("invalid length: %s", check_offset);
|
zerr("invalid length: %s", check_offset);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
if (check_offset) {
|
if (check_offset) {
|
||||||
length = mathevali(check_offset);
|
length = mathevali(check_offset);
|
||||||
|
length_set = 1;
|
||||||
if (errflag)
|
if (errflag)
|
||||||
return NULL;
|
return NULL;
|
||||||
if (length < (zlong)0) {
|
|
||||||
zerr("invalid length: %s", check_offset);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (horrible_offset_hack) {
|
if (horrible_offset_hack) {
|
||||||
|
@ -2889,8 +2887,16 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int ssub)
|
||||||
}
|
}
|
||||||
if (offset_hack_argzero)
|
if (offset_hack_argzero)
|
||||||
alen++;
|
alen++;
|
||||||
if (length < 0)
|
if (length_set) {
|
||||||
length = alen;
|
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)
|
if (offset > alen)
|
||||||
offset = alen;
|
offset = alen;
|
||||||
if (offset + length > alen)
|
if (offset + length > alen)
|
||||||
|
@ -2909,6 +2915,7 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int ssub)
|
||||||
aval = newarr;
|
aval = newarr;
|
||||||
} else {
|
} else {
|
||||||
char *sptr, *eptr;
|
char *sptr, *eptr;
|
||||||
|
int given_offset;
|
||||||
if (offset < 0) {
|
if (offset < 0) {
|
||||||
MB_METACHARINIT();
|
MB_METACHARINIT();
|
||||||
for (sptr = val; *sptr; ) {
|
for (sptr = val; *sptr; ) {
|
||||||
|
@ -2918,12 +2925,27 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int ssub)
|
||||||
if (offset < 0)
|
if (offset < 0)
|
||||||
offset = 0;
|
offset = 0;
|
||||||
}
|
}
|
||||||
|
given_offset = offset;
|
||||||
MB_METACHARINIT();
|
MB_METACHARINIT();
|
||||||
|
if (length_set && length < 0)
|
||||||
|
length -= offset;
|
||||||
for (sptr = val; *sptr && offset; ) {
|
for (sptr = val; *sptr && offset; ) {
|
||||||
sptr += MB_METACHARLEN(sptr);
|
sptr += MB_METACHARLEN(sptr);
|
||||||
offset--;
|
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; ) {
|
for (eptr = sptr; *eptr && length; ) {
|
||||||
eptr += MB_METACHARLEN(eptr);
|
eptr += MB_METACHARLEN(eptr);
|
||||||
length--;
|
length--;
|
||||||
|
|
|
@ -1366,6 +1366,7 @@
|
||||||
print ${foo:$(echo 3 + 3):`echo 4 - 3`}
|
print ${foo:$(echo 3 + 3):`echo 4 - 3`}
|
||||||
print ${foo: -1}
|
print ${foo: -1}
|
||||||
print ${foo: -10}
|
print ${foo: -10}
|
||||||
|
print ${foo:5:-2}
|
||||||
0:Bash-style offsets, scalar
|
0:Bash-style offsets, scalar
|
||||||
>456789
|
>456789
|
||||||
>56789
|
>56789
|
||||||
|
@ -1377,6 +1378,7 @@
|
||||||
>7
|
>7
|
||||||
>9
|
>9
|
||||||
>123456789
|
>123456789
|
||||||
|
>67
|
||||||
|
|
||||||
foo=(1 2 3 4 5 6 7 8 9)
|
foo=(1 2 3 4 5 6 7 8 9)
|
||||||
print ${foo:3}
|
print ${foo:3}
|
||||||
|
@ -1389,6 +1391,7 @@
|
||||||
print ${foo:$(echo 3 + 3):`echo 4 - 3`}
|
print ${foo:$(echo 3 + 3):`echo 4 - 3`}
|
||||||
print ${foo: -1}
|
print ${foo: -1}
|
||||||
print ${foo: -10}
|
print ${foo: -10}
|
||||||
|
print ${foo:5:-2}
|
||||||
0:Bash-style offsets, array
|
0:Bash-style offsets, array
|
||||||
>4 5 6 7 8 9
|
>4 5 6 7 8 9
|
||||||
>5 6 7 8 9
|
>5 6 7 8 9
|
||||||
|
@ -1400,6 +1403,7 @@
|
||||||
>7
|
>7
|
||||||
>9
|
>9
|
||||||
>1 2 3 4 5 6 7 8 9
|
>1 2 3 4 5 6 7 8 9
|
||||||
|
>6 7
|
||||||
|
|
||||||
testfn() {
|
testfn() {
|
||||||
emulate -L sh
|
emulate -L sh
|
||||||
|
@ -1438,3 +1442,13 @@
|
||||||
print ${str:0:}
|
print ${str:0:}
|
||||||
1:Regression test for missing length after offset
|
1:Regression test for missing length after offset
|
||||||
?(eval):2: unrecognized modifier
|
?(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