为什么进程替换在脚本中不起作用?

时间:2015-10-28 07:22:54

标签: bash io-redirection

简单的一行

$ read a b < <(sed -nr '$ s/.*(123).*(456).*/\1 \2/p' <<<"fds 123 fdsf 456 f")
$ echo $a - $b
123 - 456

在终端中工作,但是放在脚本中

$ echo -e '#!/bin/bash\nread a b < <(sed -nr '$ s/.*(123).*(456).*/\1 \2/p' <<<"fds 123 fdsf 456 f")\necho $a - $b' >/tmp/t
$ chmod +x /tmp/t
$ /tmp/t

它出错了

/tmp/t: command substitution: line 3: syntax error near unexpected token `('
/tmp/t: command substitution: line 3: `sed -nr $ s/.*(123).*(456).*/1 2/p <<<"fds 123 fdsf 456 f")'

我怀疑它与read因某些原因无法访问的脚本的stdin有关,但我无法弄清楚它到底需要什么。

我在写一个文件的例子中犯了一个错误,但这个问题没有实现。假设read的行在终端和脚本版本中看起来完全相同。问题是为什么它不能被放入文件中。

4 个答案:

答案 0 :(得分:2)

您没有正确编写脚本。做这样事情的最简单方法是使用heredoc:

cat > /tmp/t << \EOF
#!/bin/bash
read a b < <(sed -nr '$ s/.*(123).*(456).*/\1 \2/p' <<<"fds 123 fdsf 456 f")
echo $a - $b
EOF
chmod +x /tmp/t
/tmp/t

答案 1 :(得分:2)

您在两个完全不同的引用场景中使用进程替换。第一:

read a b < <(sed -nr '$ s/.*(123).*(456).*/\1 \2/p' <<<"fds 123 fdsf 456 f")

您正在使用流程替换将结果提供给read

sed -nr '$ s/.*(123).*(456).*/\1 \2/p' <<<"fds 123 fdsf 456 f"

到您的阅读声明 - 这很好。没有引用问题。 (但是,当简单重定向应该这样做时,你使用 herestring 是可疑的。)

在第二个命令行/脚本尝试中:

$ echo -e '#!/bin/bash\nread a b < <(sed -nr '$ s/.*(123).*(456).*/\1 \2/p' <<<"fds 123 fdsf 456 f")\necho 

您使用单引号是不正确的,它会提前终止您的命令,使其不完整。用双引号替换第二组单引号(反之亦然):

echo -e '#!/bin/bash\nread a b < <(sed -nr "$ s/.*(123).*(456).*/\1 \2/p" <<<"fds 123 fdsf 456 f")\necho'

echo对过程替换一无所知,它只知道它何时有一个开放的单引号',然后下一个应该是一个结束单引号......

答案 2 :(得分:2)

问题在于引用,使用它来编写脚本:

cat <<'EOF' >script
#!/bin/bash
read a b < <(sed -nr '$ s/.*(123).*(456).*/\1 \2/p' <<<"fds 123 fdsf 456 f")
echo $a $b
EOF

here-document <<'EOF'中的引号禁用脚本中的参数扩展。

答案 3 :(得分:0)

虽然我仍然不明白为什么流程替换不起作用,但这种解决方法对我有帮助

read a b <<EOF
$(sed -nr '$ s/.*(123).*(456).*/\1 \2/p' <<<"fds 123 fdsf 456 f")
EOF

您可能需要在sed之前指定IFS,例如

$(IFS=' '; sed -nr '$ s/.*(123).*(456).*/\1 \2/p' <<<"fds 123 fdsf 456 f")

这个例子。

相关问题