diff options
-rw-r--r-- | shell/ash.c | 17 | ||||
-rw-r--r-- | shell/ash_test/ash-vars/var_bash4.right | 2 | ||||
-rwxr-xr-x | shell/ash_test/ash-vars/var_bash4.tests | 2 |
3 files changed, 16 insertions, 5 deletions
diff --git a/shell/ash.c b/shell/ash.c index 6befe0fd3..4fbae2498 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -6234,7 +6234,7 @@ parse_sub_pattern(char *arg, int varflags) unsigned char c; //char *org_arg = arg; - //bb_error_msg("arg:'%s'", arg); + //bb_error_msg("arg:'%s' varflags:%x", arg, varflags); idx = arg; while (1) { c = *arg; @@ -6248,9 +6248,20 @@ parse_sub_pattern(char *arg, int varflags) } } *idx++ = c; - if (!(varflags & VSQUOTE) && c == '\\' && arg[1] == '\\') - arg++; /* skip both \\, not just first one */ arg++; + /* + * Example: v='ab\c'; echo ${v/\\b/_\\_\z_} + * The result is a_\_z_c (not a\_\_z_c)! + * + * Enable debug prints in this function and you'll see: + * ash: arg:'\\b/_\\_z_' varflags:d + * ash: pattern:'\\b' repl:'_\_z_' + * That is, \\b is interpreted as \\b, but \\_ as \_! + * IOW: search pattern and replace string treat backslashes + * differently! That is the reason why we check repl below: + */ + if (c == '\\' && *arg == '\\' && repl && !(varflags & VSQUOTE)) + arg++; /* skip both '\', not just first one */ } *idx = c; /* NUL */ //bb_error_msg("pattern:'%s' repl:'%s'", org_arg, repl); diff --git a/shell/ash_test/ash-vars/var_bash4.right b/shell/ash_test/ash-vars/var_bash4.right index 2d4e45be8..600e8532f 100644 --- a/shell/ash_test/ash-vars/var_bash4.right +++ b/shell/ash_test/ash-vars/var_bash4.right @@ -11,7 +11,7 @@ Quoted: a*b_\_\z_ Source: a\bc Replace str: _\\_\z_ -Pattern: single backslash and b: "replace literal b" +Pattern: single backslash and b: "replace b" In assignment: a\_\_z_c Unquoted: a\_\_z_c Quoted: a\_\_\z_c diff --git a/shell/ash_test/ash-vars/var_bash4.tests b/shell/ash_test/ash-vars/var_bash4.tests index a6e98fd86..d5470614b 100755 --- a/shell/ash_test/ash-vars/var_bash4.tests +++ b/shell/ash_test/ash-vars/var_bash4.tests @@ -30,7 +30,7 @@ v='a\bc' echo 'Source: ' "$v" echo 'Replace str: ' '_\\_\z_' -echo 'Pattern: ' 'single backslash and b: "replace literal b"' +echo 'Pattern: ' 'single backslash and b: "replace b"' r=${v/\b/_\\_\z_} echo 'In assignment:' "$r" echo 'Unquoted: ' ${v/\b/_\\_\z_} |