【发布时间】:2024-01-11 05:38:01
【问题描述】:
我使用的是 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尝试扩展命令seen,这当然不知道,因为它是一个变量名。但它不应该发生,因为命令放在单引号内。
echoing 在单引号多行输入中效果很好:
$ 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
我查看了 rici 在 how to address error “bash: !d': event not found” in Bash command substitution 上的规范答案,发现了许多可能的原因,但没有一个符合这种行为。
【问题讨论】:
-
似乎最后一行被解析为单行,而不是包含之前引用的字符串。这意味着
!的处理就像它是在双引号中一样。您还会注意到,您将在下一行得到一个>,因为它正在等待您关闭这个感知到的引用字符串。这就是它也适用于单行的原因。看起来像一个错误。 -
可在 4.2.47 中重现。我会提交一个错误。
-
也可以一直重现到
3.2.51 -
$ ls<press enter here>$ echo "<press enter here>asdasd<another enter here>" | echo '!!'将打印奇怪的输出... -
@anishsane 与
!#相同,但不是您所期望的,请尝试echo "<ENTER>123<ENTER>" | awk '!#'。它返回" | awk '" | awk ''
标签: bash gnu command-substitution