结合GNU Parallel并行化jq命令遇问题:引号错误与命令行过长
我尝试用GNU Parallel并行化一段jq命令,但始终无法正常运行,以下是详细情况:
原始可正常运行的jq命令
jq --raw-output '._id as $id | ._source.CitationTextHeader.Article.AuthorList[]? | .Affiliation.Affiliation | [ $id, .[0:rindex(" Electronic address:")] ] | @csv' results.json > test.out
第一次尝试的Parallel命令及错误
我使用以下命令结合Parallel:
parallel -j0 --keep-order --spreadstdin "jq --raw-output '._id as $id | ._source.CitationTextHeader.Article.AuthorList[]? | .Affiliation.Affiliation | [ $id, .[0:rindex(" Electronic address:")] ] | @csv'" < results.json > test.json
出现编译错误:
jq: error: syntax error, unexpected '|', expecting '$' or '[' or '{' (Unix shell quoting issues?) at
, line 1:
._id as | ._source.CitationTextHeader.Article.AuthorList[]? | .Affiliation.Affiliation | [ , .[0:rindex( Electronic address:)] ] | @csv
jq: 1 compile error
我推测是引号转义的问题,但错误提示不够明确。
第二次尝试的命令及新错误
参考其他帖子后,我调整为以下命令:
parallel -a results.json --results test.json -q jq -r '._id as $id | ._source.CitationTextHeader.Article.AuthorList[]? | .Affiliation.Affiliation | [ $id, .[0:rindex(" Electronic address:")] ] | @csv'
现在出现新错误:
parallel: Error: Command line too long (76224 >= 63664) at input 0:
JSON文件示例(单条记录)
{ "_index": "corpuspm", "_type": "_doc", "_id": "6786777", "_score": 1, "_source": { "CitationTextHeader": { "Article": { "AuthorList": [ { "Affiliation": { "Affiliation": "title, society, American Pediatric Society. address@hotmail.com." } } ] } } } }
问题分析与解决办法
1. 第一次错误:Shell引号转义问题
$id在双引号中会被Shell解析为空变量,导致jq命令里的._id as $id变成._id as ;同时内层的双引号" Electronic address:"被Shell拆分,直接破坏了jq语法结构。
解决命令:
避免将jq命令包裹在双引号中,改用-q参数让Parallel处理引号转义,或者直接将jq脚本作为独立参数传递:
parallel -j0 --keep-order --spreadstdin -q jq -r '._id as $id | ._source.CitationTextHeader.Article.AuthorList[]? | .Affiliation.Affiliation | [ $id, .[0:rindex(" Electronic address:")] ] | @csv' < results.json > test.json
2. 第二次错误:命令行过长
-a results.json会把整个文件当作单个参数传给Parallel,如果你的JSON不是每行一个对象的JSON Lines格式,就会导致命令行长度超出系统限制。
分场景解决:
- 如果你的JSON是数组结构:先拆分成每行一个对象再并行处理
jq -c '.[]' results.json | parallel -j0 --keep-order jq -r '._id as $id | ._source.CitationTextHeader.Article.AuthorList[]? | .Affiliation.Affiliation | [ $id, .[0:rindex(" Electronic address:")] ] | @csv' > test.json - 如果你的JSON本身就是每行一个独立对象:直接用
-a读取每行parallel -j0 --keep-order -a results.json jq -r '._id as $id | ._source.CitationTextHeader.Article.AuthorList[]? | .Affiliation.Affiliation | [ $id, .[0:rindex(" Electronic address:")] ] | @csv' > test.json
内容的提问来源于stack exchange,提问作者AJW

