我猜这与ack
无关,但与bash
无关:
我们在此创建包含字符串file.txt
的{{1}},以便foobar
可以在其中找到ack
:
foobar
到目前为止一切顺利。为什么不在这里找到任何东西?
> echo foobar > file.txt
> echo 'ack foobar file.txt' > ack.sh
> bash ack.sh
foobar
> bash < ack.sh
foobar
或
> cat ack.sh | bash
(no output)
为什么> echo 'ack foobar file.txt' | bash
(no output)
在最后两种情况下找不到ack
?
在前面添加foobar
(来自expect)会让它起作用,我不明白:
unbuffer
更奇怪的是:
> echo 'unbuffer ack foobar file.txt' | bash
foobar
使用此输出进行Wassup?它回声> cat ack2.sh
echo running
ack foobar file.txt
echo running again
unbuffer ack foobar file.txt
# Behaves as I'd expect
> bash ack2.sh
running
foobar
running again
foobar
# Strange output
> cat ack2.sh | bash
running
unbuffer ack foobar file.txt
但不是
unbuffer ack foobar file.txt
?咦?
答案 0 :(得分:4)
ack
感到困惑,因为stdin是管道而不是终端。您需要传递--nofilter
选项以强制ack
将stdin视为tty。
此:
# ack.sh
ack --nofilter foobar file.txt
工作的:
$ cat ack.sh | bash
foobar
如果你问我,那种行为是非常意外的。当有人理解ack
我不理解的概念时,可能会发生这种情况。我希望ack
在传递文件名参数时不会查看标准输入。
为什么unbuffer
“解决”问题?
unbuffer
,跟随它man page,不会尝试从标准输入读取:
Normally, unbuffer does not read from stdin. This simplifies use of unbuffer in some situations. To use unbuffer in a pipeline, use the -p flag. ...
看起来ack
试图 这里的stdin很聪明。如果它为空,则不会从stdin
读取并查看传递给它的文件名。再次,如果存在filename参数,那么根本不查看stdin是正确的。
答案 1 :(得分:1)
这里的大不匹配是ack从未打算用在shell脚本中。它意味着作为人类的命令行工具。这意味着它为人类做出了一些假设和优化。例如,默认情况下,如果ack的输出到达终端而不是在管道中重定向,则ack的输出是不同的。在shell脚本中使用ack也存在危险,因为它的行为会受到ackrc文件和环境变量的影响。如果您要在脚本中使用ack,则应使用Fade
标志。更好的是,对于shell脚本,我会使用普通的'grep。
提出这个问题的用例是什么?
答案 2 :(得分:0)
我同意这是一个错误 - ack 可以查看标准输入,但是以非阻塞的方式。挂在空的管道上是一个错误......