Using current git busybox master (0e0209a) on Ubuntu 16.04 . To reproduce, run inside ash: (x=AB; echo "${x#$'\x41'}") Expected result (and actual result in bash): B Actual result: AB If removing the quotes then it works as expected and like bash: (x=AB; echo ${x#$'\x41'}) B Other cases where busybox ash works correctly - i.e. like in bash: (x=AB; y=A; echo "${x#$y}") # B echo $'\x41' # A echo "$'\x41'" # $'\x41' And more cases where ash works correctly and demonstrates quoted vs unquoted pattern inside quoted braces expansion: (x="*ABC"; echo "${x#*B}") # C (x="*ABC"; echo "${x#"*B"}") # *ABC I don't think posix has anything specific to say, as it's a bash feature, but it does seem to me that the outer quotes should not affect how things work inside the braces, and the spec does say the following about parameter expansion - note how it relates to the result of the expansion and not how the expansion itself works: If a parameter expansion occurs inside double-quotes: - Pathname expansion shall not be performed on the results of the expansion. - Field splitting shall not be performed on the results of the expansion, with the exception of '@' ; see Special Parameters. And about braced quotes with word like ${parameter<something>word} : In each case that a value of word is needed (based on the state of parameter, as described below), word shall be subjected to tilde expansion, parameter expansion, command substitution, and arithmetic expansion. And about pattern expansion like ${parameter#word} , specifically the last two sentances about quotes: In each case, pattern matching notation (see Pattern Matching Notation), rather than regular expression notation, shall be used to evaluate the patterns. If parameter is '*' or '@', the result of the expansion is unspecified. Enclosing the full parameter expansion string in double-quotes shall not cause the following four varieties of pattern characters to be quoted, whereas quoting characters within the braces shall have this effect. --------- Overall, it seems to me that bash-dollar should be expanded inside quoted braced expansion, both because it seems to me that inside-the-braces should not be affected by what happens with the result, because the posix spec seem to support this approach in general, and because bash does so and ultimately it's a bash feature. Real world case: git-prompt.sh (distributed with git) uses such bash-dollar inside braces expansion inside quotes (to split by newlines $'\n').
And a similar "incorrect" (compared to bash) case, this time without a pattern: $ (unset x; echo "${x-$'\x41'}") Where ash prints $'\x41' while bash prints A, but if removing the outer quotes then both ash and bash print A .
Adding some info from conversation with @vda on IRC: <vda> there is work happening in dash on this, I prefer to wait for them to have a solution, to not have diverging code ... <vda> search for: <vda> dash bug: double-quoted "\" breaks glob protection for next char
Not sure if related, but I believe the following commit (before this report): 2018-02-13 8de5b9f ash : fix double-quoted "\z" handling Broke at least one correct case - the key is that pattern in ${param#pattern} should be considered unquoted regardless if the whole expansion is or isn't quoted: OK before: (x=\'B; echo "${x#\'}") B Bad after: (x=\'B; echo "${x#\'}") 'B The following didn't change with 8de5b9f : OK both before and after: (x=\'B; echo "${x#"'"}") B I believe bad before and after - should error on unterminated string: (x=\'B; echo "${x#'}") B The original report also didn't change - same before/after: (x=AB; echo "${x#$'\x41'}") AB
(In reply to avih from comment #3) : pattern in ${param#pattern} should be considered unquoted regardless if the whole expansion is or isn't quoted Well, it does not look like it works that way in bash: $ x='a]'; echo _${x#[a]]}_ __ $ x='a]'; echo _${x#[a\]]}_ _]_ $ x='a]'; echo "_${x#[a]]}_" __ $ x='a]'; echo "_${x#[a\]]}_" _]_
>> pattern in ${param#pattern} should be considered unquoted regardless if the whole expansion is or isn't quoted >> Well, it does not look like it works that way in bash: Not sure how bash is related. This is a POSIX thing, which says the following about ${param#pattern}: > Enclosing the full parameter expansion string in double-quotes shall not cause > the following four varieties of pattern characters to be quoted, whereas > quoting characters within the braces shall have this effect. Regardless though, I also don't think your examples demonstrate that bash disagrees with this posix definition. My main argument is that quoting the entire expansion doesn't change the result. However, I do think bash exhibits incorrect behavior at _${x#[a\]]}_ -> _]_ I believe bash interprets the pattern _${x#[a\]]}_ as if it was _${x#[]a]}_ i.e. only character class pattern of the char ']' or the letter 'a' . i.e. it takes \] as a literal char to be matched in the class. But this is incorrect by posix. The bracket pattern spec clearly says that \ loses its special meaning inside the brackets, and ] can only be in a character class as the first char. Therefore the pattern _${x#[a\]]}_ should mean (in posix): first char which is the letter 'a' or backslash, followed by ], which does match the whole of x, therefore as far as I can tell, it should have resulted in __ . This is a bash bug IMO, but not related to interpreting the pattern quoted or unquoted. As far as I can tell, and in your examples and mine, bash interprets it always unquoted.
Also, as for this: > OK before 8de5b9f ash : fix double-quoted "\z" handling : > (x=\'B; echo "${x#\'}") > B > Bad after: > (x=\'B; echo "${x#\'}") > 'B All the shells I tested (and posix as far as I can tell) agree it should print B, and only ash after that commit prints 'B . I tested bash (and in posix mode), dash, mksh (and in posix mode), busybox ash (before this commit). I think it should be considered a non-disputable breakage.
> Also, as for this: > > OK before 8de5b9f ash : fix double-quoted "\z" handling : > (x=\'B; echo "${x#\'}") > B > > Bad after: > (x=\'B; echo "${x#\'}") > 'B Also, with your 4 examples, all shells agree on all 4 results, except ash after 8de5b9f which disagrees on this specific case and behaves like so: x='a]'; echo "_${x#[a\]]}_" __ Where all other shells (including ash before 8de5b9f) print __]__ .
fixed in git, "ash: parser: Add syntax stack for recursive parsing" commit