我在 GNU bash,版本 4.3.11。
假设我想在文件上打印唯一行。我正在使用这种方法,它适用于文件:
$ cat a
9
10
9
11
$ awk '!seen[$0]++' a
9
10
11
但是,如果我从标准输入获取输入,在多行中使用双引号并通过管道连接到 awk,则会失败:
$ echo "9
> 10
> 9
> 11" | awk '!seen[$0]++'
bash: !seen[$0]++': event not found
也就是 bash 试图扩展 command 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
会关闭历史记录,因此它运行良好,因为它不会尝试扩展任何内容:
$ set +H
$ echo "9
> 10
> 9
> 11" | awk '!seen[$0]++'
9
10
11
我浏览了 rici 关于如何在 Bash 命令替换中解决错误“bash: !d': event not found”的规范答案,发现了许多可能的原因,但没有一个与这种行为匹配。