如何修复不正确的gnu并行子串提取

问题描述 投票:1回答:1

我试图在与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并行假设函数内部存在变量并且不是ony括号。

bash gnu-parallel
1个回答
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将它分成两个独立的args,{}。就像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示例仍然打印与以前相同,但原因不同。你正在尝试使用readbar的第一个参数array改为IFS=', ',但是你的输入不包含任何逗号(或空格),所以每次都得到一个元素的数组,并且array[1]扩展为空。

但是,如果你这样做,它可以工作(或者至少我认为它确实 - 我不确定你的预期输出是什么):

values=( "1,2" "3,4" )
parallel echo '$(bar {} )' ::: "${values[@]}"
1 2
3 4
© www.soinside.com 2019 - 2024. All rights reserved.