GNU parallel:如何使用空字符串参数调用导出的 bash 函数?

GNU parallel:如何使用空字符串参数调用导出的 bash 函数?

设想:

$ 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

相关内容