Doesn't sh support process substitution <(…

2019-02-22 12:15发布

On a Centos 6 machine, this works:

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

and this doesn't:

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

I get:

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'

Nevermind the grep and tail. The problem is with the process substitution thingy: <(...)

Can someone tell me what sh does differently here?

[EDIT]

Thanks for the answers!

The problem arose while using capistrano for deployments. It defaults to using sh but I changed that to bash now. The reason I couldn't do the normal piping is that when using tail -F | grep -q --line-buffered, grep won't exit immediately after a match. There has to be one more edit to the file like echo "" >> catalina.out and this was not acceptable in my situation.

标签: linux bash sh
3条回答
Ridiculous、
2楼-- · 2019-02-22 12:36

The syntax <(...) is only supported by BASH.

For any POSIX shell, use this approach:

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

i.e. move the stdin redirection in front of the if with a pipe. The if will pass stdin on to the grep.

if tail ...| grep won't work since the if won't be able to see it's then/fi because the pipe separates processes.

查看更多
该账号已被封号
3楼-- · 2019-02-22 12:47

You should note that process substitution (<(...)) isn't specified by POSIX. So if you were running bash in POSIX mode by invoking it with sh or saying:

set -o posix

then you'd observe errors!

From the bash manual:

Starting Bash with the --posix command-line option or executing ‘set -o posix’ while Bash is running will cause Bash to conform more closely to the POSIX standard by changing the behavior to match that specified by POSIX in areas where the Bash default differs.

...

Process substitution is not available.

查看更多
祖国的老花朵
4楼-- · 2019-02-22 12:53

Also take note that if Bash is invoked with the name sh, it tries to mimic the startup behavior of historical versions of sh as closely as possible, while conforming to the POSIX standard as well.

If your sh is actually a link to bash, then this is what's causing that.

Running sh --version; sh -c ': <(echo a)' should give you enough info.

查看更多
登录 后发表回答