如何通过GNU parallel向自定义Bash函数传递参数
GNU Parallel调用自定义Bash函数传参错误修复方案
错误原因
- 参数传递模式不匹配:你添加了
--pipepart、--block参数,这是GNU Parallel的管道分块模式,输入内容会通过标准输入传给执行的命令,而非作为位置参数$1传入,所以你写的{}占位符无法获取到每行内容,函数读取$1自然为空。 - 管道逻辑错误:你写的
_fix_col_number {} | _unify_null_value {}中,管道在Parallel命令的外层,只会把Parallel整体的输出传给_unify_null_value,后者的{}不会被Parallel解析,也不会逐行处理。 - 未显式指定执行Shell:部分系统默认sh不支持Bash导出的自定义函数,可能导致函数无法被识别。
修复方案
方案1:逐行传参模式(适合中小文件)
如果你的需求是逐行读取文件内容,将每行内容作为参数传给自定义函数处理,修改后的Parallel命令如下:
parallel -a "$file" \ -k \ -j8 \ --bar \ --will-cite \ --shell bash \ '_unify_null_value "$(_fix_col_number "{}")"' >> "$OUTPUT_DIR/$new_filename"
注意:这里把两个函数的调用嵌套在同一个命令字符串中,确保
{}被Parallel正确解析为每行内容,传入第一个函数后再将输出作为参数传给第二个函数。
方案2:分块处理模式(适合超大文件,性能更高)
如果你需要保留--block 100M、--pipepart的分块逻辑提升大文件处理性能,需要调整自定义函数读取标准输入而非位置参数$1:
- 调整处理函数:
_unify_null_value() { local _string=${1:-$(cat)} echo "$_string" | perl -0777 -pe "s/(?<=\t)\.(?=\s)//g" | \ perl -0777 -pe "s/(?<=\t)NA(?=\s)//g" | \ perl -0777 -pe "s/(?<=\t)No Info(?=\s)//g" } _fix_col_number() { local line while read -r line; do local line_cols=$(echo "$line" | awk -F"\t" '{ print NF }') if [[ $line_cols -gt $NUM_OF_COLUMNS ]]; then local new_line=$(echo "$line" | cut -f1-"$NUM_OF_COLUMNS") echo -e "$new_line" elif [[ $line_cols -lt $NUM_OF_COLUMNS ]]; then local missing_columns=$(( NUM_OF_COLUMNS - line_cols )) local new_line="${line//$'\n'/}$(_add_tabs $missing_columns)" echo -e "$new_line" else echo -e "$line" fi done }
- 调整Parallel命令:
parallel -a "$file" \ -k \ -j8 \ --block 100M \ --pipepart \ --bar \ --will-cite \ --shell bash \ '_fix_col_number | _unify_null_value' >> "$OUTPUT_DIR/$new_filename"
内容的提问来源于stack exchange,提问作者user1261558
相关产品推荐
相关产品推荐

