如何用xargs/parallel实现Bash中逐行映射stdin到工具进程
逐行将stdin内容传入独立进程处理的实现方案
需求:将stdin的每一行内容,分别传入目标工具(如jj key,仅接受stdin输入)的独立进程中处理,替代冗长且低效的while循环写法:
cat out.ndjson | while read p; do \ echo "$p" | jj key done
测试用示例文件生成
先生成测试用的ndjson文件:
cat > out.ndjson <<- EOM {"key": "line1"} {"key": "line2"} {"key": "line3"} EOM
jj工具可通过brew install tidwall/jj/jj安装,或下载二进制文件/从源码编译。
方案1:用xargs实现
xargs可通过-I参数指定替换占位符,结合sh -c将每行内容传入目标命令的stdin:
# 基础写法,适合无空格的行 cat out.ndjson | xargs -I {} sh -c 'echo "{}" | jj key'
如果行内包含空格,需指定按换行符分割输入,避免xargs误拆分内容:
cat out.ndjson | xargs -d '\n' -I {} sh -c 'jj key <<< "{}"'
这里用<<<(here-string)替代echo,效率更高且能更好保留特殊字符。
方案2:用GNU Parallel实现
GNU Parallel专为并行处理设计,天生支持逐行将内容传入命令stdin,写法更简洁:
# 单进程逐行处理 cat out.ndjson | parallel 'jj key <<< {}'
如需并行加速,可通过-j参数指定并发进程数(比如-j4启用4个进程):
cat out.ndjson | parallel -j4 'jj key <<< {}'
Parallel默认会正确处理含空格的行,无需额外指定分隔符。
方案3:用Bash函数实现maplines
如果不想依赖外部工具,可编写Bash函数实现maplines功能:
maplines() { while IFS= read -r line; do "$@" <<< "$line" done }
使用方式完全符合预期:
cat out.ndjson | maplines jj key
IFS= read -r确保读取行时保留开头/结尾的空格,以及不转义反斜杠等特殊字符。
内容的提问来源于stack exchange,提问作者Cornelius Roemer
相关产品推荐
相关产品推荐

