On 8/9/25 16:40, Robert Elz wrote:
| Lets just choose one behavior, and add it to our testsuites | to "solidify" it, so that it doesn't changes unnoticed | in the future. Which one should be picked?
Ok, I'll try ${VAR#PATTERN}: PATTERN is processed and then given (on the C level) to fnmatch() (or fnmatch()-equivalent internal matching function) to match beginning of VAR. The parts of the PATTERN may contain variables and may be quoted with "" or unquoted. The quoted parts are processed to add glob pattern escapes to characters like *, ?, \, [ to match everything literally. The shell should try to correctly escape only those characters which do need escaping: "[a]" should be escaped as "\[a]", but "[]" does not need escaping, etc. (This may be impractical to get totally correct since the shell may not know what types of [...] libc implements in fnmatch(), there are various ... "extensions" in various libcs). If an unquoted part of PATTERN results in an unpaired backslash, it is preserved and concatenated to the remaining part of PATTERN, if any: backslash='\' asterisk='*' $backslash in PATTERN expands to \ $backslash* in PATTERN expands to \* $backslash$asterisk in PATTERN expands to \* $backslash"*" in PATTERN expands to \\* $backslash"$asterisk" in PATTERN expands to \\* (the last two rules somewhat unexpectedly will NOT match '*' as literal) If shell implements internal fnmatch(), the trailing incomplete backslash should match one '\' character: VAR='\abc'; ${VAR#$backslash} returns 'abc' (Users are recommended to use ${VAR#"$backslash"} to not depend on it)