我尝试在与gnu parallel混合的bash脚本中使用子字符串提取。但是下面的代码(从更为复杂的情况简化)会产生错误的结果。
#!/bin/bash
function foo(){
echo "${1:0:1} ${1:1:1}" # substring extraction
}
function bar(){
IFS=', ' read -r -a array <<< "${1}" # string to array conversion
echo "${array[0]} ${array[1]}"
}
export -f foo
export -f bar
values=( '12' '34' )
parallel echo $(foo {} ) ::: "${values[@]}"
# produces wrong output...
# {} 12
# {} 34
parallel echo $(bar {} ) ::: "${values[@]}"
# produces wrong output...
# 12
# 34
您能否提供一些提示,我如何才能说服gnu parallel假设函数内部存在一个变量而不是方括号。
答案 0 :(得分:2)
我认为您所缺少的是,bash
在将参数传递到$(foo {} )
之前将进行parallel
的过程替换。如果将parallel
替换为printf "%s\n"
,则会看到以下内容:
printf "%s\n" echo $(foo {} ) ::: "${values[@]}"
echo
{
}
:::
12
34
这意味着您的命令与此等效:
parallel echo { } ::: 12 34
以及为什么它打印{ } 12
和{ } 34
。这里没有{}
可以替换parallel
,因为foo
已将其拆分为两个单独的参数{
和}
。就像xargs
在没有{}
时所做的一样,parallel
只是将args附加到命令的末尾,产生命令:
echo { } 12
echo { } 34
要延迟流程替换,您需要将其用单引号引起来:
parallel echo '$(foo {} )' ::: "${values[@]}"
但是,这导致了另一个问题,因为parallel
产生的进程无法识别功能foo
。但是您可以使用export -f
解决此问题:
export -f foo
parallel echo '$(foo {} )' ::: "${values[@]}"
1 2
3 4
与您的bar
示例类似。
编辑:您的bar
示例的打印内容与以前一样,只是出于不同的原因。您尝试使用read
将bar
的第一个参数array
插入IFS=', '
,但是您的输入不包含任何逗号(或空格),因此得到每次由一个元素组成的数组,并且array[1]
扩展为空。
但是,如果您改为执行此操作,则它可以工作(或者至少我认为它可以工作-我不确定此示例的预期输出是什么):
values=( "1,2" "3,4" )
parallel echo '$(bar {} )' ::: "${values[@]}"
1 2
3 4