为什么`ack`与`bash`这样使用时不会产生输出?

时间:2017-07-14 05:48:35

标签: bash ack

我猜这与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?咦?

3 个答案:

答案 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 可以查看标准输入,但是以非阻塞的方式。挂在空的管道上是一个错误......