5

在 Centos 6 机器上,这是有效的:

bash -c 'if grep -qP --line-buffered ".+" <(tail -n 1000 -F catalina.out) ; then echo "yes"; fi'

这不会:

sh -c 'if grep -qP --line-buffered ".+" <(tail -n 1000 -F catalina.out) ; then echo "yes"; fi'

我得到:

sh: -c: line 0: syntax error near unexpected token `('
sh: -c: line 0: `if grep -qP --line-buffered ".+" <(tail -n 1000 -F catalina.out) ; then echo "yes"; fi'

没关系 grep 和 tail。问题在于进程替换的东西:<(...)

有人能告诉我 sh 在这里有什么不同吗?

[编辑]

感谢您的回答!

使用capistrano进行部署时出现了问题。它默认使用sh但我现在将其更改为bash。我无法进行正常管道的原因是使用tail -F | grep -q --line-bufferedgrep 时不会在比赛后立即退出。必须对文件再进行一次编辑,echo "" >> catalina.out这在我的情况下是不可接受的。

4

3 回答 3

6

该语法<(...)仅受 BASH 支持。

对于任何 POSIX shell,请使用以下方法:

sh -c 'tail -n 1000 -F catalina.out | if grep -qP --line-buffered ".+" ; then ...'

if即用管道将标准输入重定向移动到前面。会将标准输入if传递给grep.

if tail ...| grep将无法工作,因为管道将进程分开if,因此无法看到它。thenfi

于 2013-09-05T08:37:26.400 回答
6

您应该注意,<(...)POSIX 没有指定进程替换 ( )。因此,如果您bash在 POSIX 模式下运行,通过调用它sh或说:

set -o posix

然后你会观察到错误!

bash 手册

--posix使用命令行选项 启动 Bash或-o posix在 Bash 运行时执行 '<code>set ' 将导致 Bash 通过更改行为以匹配 POSIX 在 Bash 默认值不同的区域中指定的行为,从而更加符合 POSIX 标准。

...

进程替换不可用。

于 2013-09-05T08:53:54.770 回答
4

另请注意,如果使用名称 sh 调用 Bash,它会尽可能地模仿 sh 历史版本的启动行为,同时也符合 POSIX 标准。

如果您的 sh 实际上是 bash 的链接,那么这就是造成这种情况的原因。

跑步sh --version; sh -c ': <(echo a)'应该给你足够的信息。

于 2013-09-05T08:53:21.740 回答