我使用的是GNU bash,版本4.3.11。
说我想在文件上打印唯一的行。我正在使用这种方法,它适用于文件:
$ cat a
9
10
9
11
$ awk '!seen[$0]++' a
9
10
11
但是,如果我从stdin获取输入,在多行中使用双引号并输入到awk,则会失败:
$ echo "9
> 10
> 9
> 11" | awk '!seen[$0]++'
bash: !seen[$0]++': event not found
也就是说,bash尝试扩展命令seen
,这当然不知道,因为它是一个变量名。但它不应该发生,因为命令放在单引号内。
echo
单引号,多行输入效果很好:
$ echo '9
> 10
> 9
> 11' | awk '!seen[$0]++'
9
10
11
有趣的是,它也适用于双引号的单行输入:
$ printf "9\n10\n9\n11" | awk '!seen[$0]++'
9
10
11
我想知道为什么Bash试图扩展历史,如果它发生在多行输入后,即使命令本身使用单引号。
其他考虑因素:
介于两者之间的管道不会修复它:
$ echo "9
> 10
> 9
> 11" | cat - | awk '!seen[$0]++'
bash: !seen[$0]++': event not found
设置set +H
turns history off,因此效果不错,因为它不会尝试扩展任何内容:
$ set +H
$ echo "9
> 10
> 9
> 11" | awk '!seen[$0]++'
9
10
11
我在how to address error “bash: !d': event not found” in Bash command substitution上通过rici的规范回答,发现了很多可能的原因,但没有一个符合这种行为。
答案 0 :(得分:2)
这不是一个错误。
在bash-bugs邮件列表中询问后,我得到了以下答案:
历史扩展明确是面向行的。
它不知道shell状态,特别是shell引用状态, 跨越线条。
它确实知道模糊的贝壳式引用,这种引用在整个过程中很常见 大量的Unix实用程序 - 自历史和readline以来 库在shell之外使用 - 而且是双引号 引入了带引号的字符串,其中单引号不重要 并且不要抑制历史扩张。