设想:
$ process(){ echo "[$1] [$2] [$3]" ; } ; export -f process
$ process "x" "" "a.txt"
[x] [] [a.txt]
在这里我们看到第二个参数是空字符串(预期)。
$ find -name "*.txt" -print | SHELL=$(type -p bash) parallel process "x" ""
[x] [./a.txt] []
[x] [./b.txt] []
[x] [./c.txt] []
在这里我们看到第二个参数是 find 的输出(意外)。
预期输出:
[x] [] [./a.txt]
[x] [] [./b.txt]
[x] [] [./c.txt]
怎么修?
""
注意:如果第二个参数从to更改"y"
,则 find 的输出将作为第三个参数出现(预期):
$ find -name "*.txt" -print | SHELL=$(type -p bash) parallel process "x" "y"
[x] [y] [./a.txt]
[x] [y] [./b.txt]
[x] [y] [./c.txt]
为什么不是find 的输出作为第三个参数,带有""
?
UPD:看来解决方案是\"\"
:
$ find -name "*.txt" -print | SHELL=$(type -p bash) parallel process "x" \"\"
[x] [] [./a.txt]
[x] [] [./b.txt]
[x] [] [./c.txt]
但是,我不确定这是否是正确的通用解决方案。这是反例:
$ VAR="" ; find -name "*.txt" -print | SHELL=$(type -p bash) parallel process "x" "$VAR"
[x] [./a.txt] []
[x] [./b.txt] []
[x] [./c.txt] []
答案1
因此,通过 shell 并行运行命令,而不是直接执行它。嗯,它必须如此,否则您使用的 shell 函数将无法工作。
这也意味着带有空格的参数将被分割:
$ echo x | parallel process "foo bar" ""
[foo] [bar] [x]
如果引用单个参数或整个命令并不重要:
$ echo x | parallel "process foo bar"
[foo] [bar] [x]
你可以这样做:
$ echo x | parallel process '$(date +%F)'
[2024-02-29] [x] []
$ echo x | parallel "process foo bar > test.out"
$ cat test.out
[foo] [bar] [x]
要传递任意值,您需要为 shell 引用它们。在 Bash 中,您可以使用${var@Q}
变量的扩展:
$ var="foo bar"; echo x | parallel process "${var@Q}"
[foo bar] [x] []
并行似乎有一个选项可以做到这一点:
--quote
-q
引用命令。如果您的命令包含 shell 不应解释的特殊字符(例如;
\
|
*
),请使用--quote
对这些字符进行转义。该命令必须是一个简单的命令(请参阅 man bash),没有重定向,也没有变量分配。请参阅“引用”部分。大多数人不需要这个。默认情况下禁用引用。
$ var="foo bar"; echo x | parallel --quote process "$var"
[foo bar] [x] []
当然,这也会破坏重定向等:
$ var="foo bar"; echo x | parallel --quote process "$var" ">test.out"
[foo bar] [>test.out] [x]
当然,它会引用空格,因此如果您尝试将命令参数作为单个字符串传递,它将失败。
请注意,当您执行此操作时
$ VAR="" ; ... parallel process "x" "$VAR"
该变量仍然只包含空字符串,该字符串作为参数传递给并行。要使其与 相同parallel process "x" \"\"
,您需要在变量中使用硬引号,即VAR=\"\"
、 orVAR='""'
或等价物。或者使用类似的东西parallel process "x" "'$VAR'"
代替。请记住,如果变量本身也可以包含引号,则不能盲目地将内容括在引号中。这将失败:
$ var="ain't so"; echo x | parallel process "'$var'"
/usr/bin/bash: -c: line 1: unexpected EOF while looking for matching `''
/usr/bin/bash: -c: line 2: syntax error: unexpected end of file