hush: implement negative start in the ${v: -n[:m]} idiom

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
This commit is contained in:
Denys Vlasenko 2017-07-06 19:48:20 +02:00
parent 3234045d07
commit 5dad7bdc3b
5 changed files with 37 additions and 2 deletions

View File

@ -0,0 +1,5 @@
Expected Actual
a*z : a*z
\z : \z
a1z a2z: a1z a2z
z : z

View File

@ -0,0 +1,9 @@
# This testcase checks globbing correctness in ${v/a/b}
>a1z; >a2z;
echo 'Expected' 'Actual'
v='a bz'; echo 'a*z :' "${v/a*z/a*z}"
v='a bz'; echo '\z :' "${v/a*z/\z}"
v='a bz'; echo 'a1z a2z:' ${v/a*z/a*z}
v='a bz'; echo 'z :' ${v/a*z/\z}
rm a1z a2z

View File

@ -5619,8 +5619,12 @@ static NOINLINE const char *expand_one_var(char **to_be_freed_pp, char *arg, cha
goto arith_err;
debug_printf_varexp("len:'%s'=%lld\n", exp_word, (long long)len);
if (len >= 0) { /* bash compat: len < 0 is illegal */
if (beg < 0) /* bash compat */
beg = 0;
if (beg < 0) {
/* negative beg counts from the end */
beg = (arith_t)strlen(val) + beg;
if (beg < 0) /* ${v: -999999} is "" */
beg = len = 0;
}
debug_printf_varexp("from val:'%s'\n", val);
if (len == 0 || !val || beg >= strlen(val)) {
arith_err:

View File

@ -0,0 +1,6 @@
parameter 'abcdef'
varoffset2 'cdef'
varoffset-2 'ef'
literal '2' 'cdef'
literal '-2' 'abcdef'
literal ' -2' 'ef'

View File

@ -0,0 +1,11 @@
parameter=abcdef
offset=2
noffset=-2
echo "parameter '${parameter}'"
echo "varoffset2 '${parameter:${offset}}'"
echo "varoffset-2 '${parameter:${noffset}}'"
echo "literal '2' '${parameter:2}'"
# This is not inrpreted as ${VAR:POS{:LEN}},
# but as ${VAR:=WORD} - if VAR is unset or null, substitute WORD
echo "literal '-2' '${parameter:-2}'"
echo "literal ' -2' '${parameter: -2}'"