I took a closer look on this phenomenon after I stumbled over it in two other questions today. I’ve tried all of this with the default set -H (history expansion on).
To test a script, I often do things like echoing a multi-line string and pipe it through a script, but in some cases it gives an error:
$ echo "foo bar" | sed '/foo/!d' bash: !d': event not found >
The ! seems to trigger history expansion, although it is enclosed with single quotes. The problem seems to be the occurrence of the double quote in the same line, because
$echo $'foonbar' | sed '/foo/!d'
works as well as
$echo "foo bar" | > sed '/foo/!d'
My suspicion: History expansion is applied linewise, so the ' after a single " is considered to be escaped, so the following ! is not escaped.
Now my question: Is this a bug or expected behavior? Reproduced with bash versions 4.2.30 and 4.4.12.
Answers:
Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.
Method 1
I reported this to [email protected] and got this answer:
History expansion is explicitly line-oriented, and always has been. There’s
not a clean way to make it aware of the shell’s current quoting state
(mostly since it’s a library independent of the shell). Maybe there’s a way
to use one of the existing callback functions to do it.
This sounds to me like “this is not a bug, because we can’t do it any better with the current implementation“.
Update
I lost interest in this subject after switching to zsh. Now I tried with bash version 5.1.4 and found the problem can’t be reproduced anymore. So somewhere between 4.4.12 and 5.1.4, somebody did fix this.
All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0