如何修复不正确的 gnu 并行子字符串提取
how to fix incorrect gnu parallel substring extraction
我尝试在 bash 脚本中使用子字符串提取与 gnu 并行。但是下面的代码(从更复杂的案例中简化而来)产生了错误的结果。
#!/bin/bash
function foo(){
echo "${1:0:1} ${1:1:1}" # substring extraction
}
function bar(){
IFS=', ' read -r -a array <<< "" # 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 假设函数内部的一个变量存在,而不是只有括号。
我认为您缺少的是 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
我尝试在 bash 脚本中使用子字符串提取与 gnu 并行。但是下面的代码(从更复杂的案例中简化而来)产生了错误的结果。
#!/bin/bash
function foo(){
echo "${1:0:1} ${1:1:1}" # substring extraction
}
function bar(){
IFS=', ' read -r -a array <<< "" # 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 假设函数内部的一个变量存在,而不是只有括号。
我认为您缺少的是 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