Bash History Expansion – Inside Single Quotes After Double Quote

bashhistory-expansionquoting

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 $'foo\nbar' | 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.

Best Answer

I reported this to bug-bash@gnu.org 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".

I think I'll suggest a patch for the man page at least, so this limitation will be documented in the future.

Next reason to switch to zsh

Related Question