6

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.

Philippos
  • 13,453
  • 1
    Just tried with zsh (history expansion on): No such problem. Really seems to be a bug in bash – Philippos Sep 08 '17 at 07:54
  • 1
    The problem is poor implementation of history expansion in bash. You can disable the whole implementation by adding set +H to .bashrc. In that case, bash never attempts to do any history expansion stuff anywhere (that is, behave like proper bourne shell) and you'll have less nasty surprises. – Mikko Rantalainen Nov 14 '18 at 07:41

1 Answers1

6

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".

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.

Philippos
  • 13,453