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

Pet*_*rch 6 bash ack

我猜这与此无关,ack但更多的是bash:

这里我们创建file.txt包含字符串,foobar因此ack可以foobar在其中找到:

> echo foobar > file.txt
> echo 'ack foobar file.txt' > ack.sh
> bash ack.sh
foobar
> bash < ack.sh
foobar
Run Code Online (Sandbox Code Playgroud)

到现在为止还挺好.为什么不在这里找到任何东西?

> cat ack.sh | bash
(no output)
Run Code Online (Sandbox Code Playgroud)

要么

> echo 'ack foobar file.txt' | bash
(no output)
Run Code Online (Sandbox Code Playgroud)

为什么在最后两个案例中ack找不到foobar

unbuffer在前面添加(从期望)使它工作,我不明白:

> echo 'unbuffer ack foobar file.txt' | bash
foobar
Run Code Online (Sandbox Code Playgroud)

更奇怪的是:

> 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
Run Code Online (Sandbox Code Playgroud)

Wassup有这个输出?它回声unbuffer ack foobar file.txt但不是 running again吗?咦?

hek*_*mgl 5

ack因为 stdin 是管道而不是终端而感到困惑。您需要传递--nofilter选项以强制ack将 stdin 视为 tty。

这:

# ack.sh
ack --nofilter foobar file.txt
Run Code Online (Sandbox Code Playgroud)

作品:

$ cat ack.sh | bash
foobar
Run Code Online (Sandbox Code Playgroud)

如果你问我的话,我会说这种行为是相当出乎意料的。ack当有人理解我不明白的概念时,这可能是预料之中的。我希望当ack文件名参数传递给它时不会查看标准输入。


为什么能unbuffer“解决”问题?

unbuffer,遵循其手册页,不会尝试从标准输入读取:

  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. ...
Run Code Online (Sandbox Code Playgroud)

看起来也想ack尝试一下这里关于 stdin 很聪明。如果它为空,则不会读取stdin并查看传递给它的文件名。同样,在我看来,如果存在文件名参数,则根本不查看 stdin 是正确的。