给出以下输入:
J='{"a":1,"b":10,"c":100}
{"a":2,"b":20,"c":200}
{"a":3,"b":30,"c":300}'
命令
SELECT='a,b'; echo $J | jq -c -s --arg P1 $SELECT '.[]|{a,b}'
生成
{"a":1,"b":10}
{"a":2,"b":20}
{"a":3,"b":30}
但是此命令会产生意外结果:
SELECT='a,b'; echo $J | jq -c -s --arg P1 $SELECT '.[]|{$P1}'
{"P1":"a,b"}
{"P1":"a,b"}
{"P1":"a,b"}
如何让jq直接处理arg字符串?
使用tostring会出错
SELECT='a,b'; echo $J | jq -c -s --arg P1 $SELECT '.[]|{$P1|tostring}'
jq: error: syntax error, unexpected '|', expecting '}' (Unix shell quoting
issues?) at <top-level>, line 1:
.[]|{$SELECT|tostring}
jq: 1 compile error
SELECT需要是一个变量,而不是在脚本中硬编码。
答案 0 :(得分:2)
这不是--arg
的合适用例。相反,替换为代码:
select='a,b'; jq -c -s '.[]|{'"$select"'}' <<<"$j"
请注意,这具有代码注入的所有常见警告:如果输入不受控制,则输出(或脚本的其他行为,特别是jq
将来获得更强大的I / O功能时)应该同样可以考虑。
在这里,我们采用您的select_str
(a,b
形式),并生成地图:{'a': 'a', 'b': 'b'}
;然后,我们可以将每个数据项分成条目,只选择地图中的项目,然后输出。
jq --arg select_str "$select" '
($select_str
| split(",")
| reduce .[] as $item ({}; .[$item]=$item)) as $select_map
| with_entries(select($select_map[.key]))' <<<"$j"
答案 1 :(得分:2)
SELECT需要是一个变量,而不是在脚本中硬编码。
假设您希望避免“代码注入”的风险,并且您希望shell变量SELECT是一个简单的字符串,例如“a,b”,那么请考虑您尝试的这种无减少解决方案:
J='{"a":1,"b":10,"c":100}'
SELECT='a,b'
echo "$J" |
jq -c --arg P1 "$SELECT" '
. as $in | $P1 | split(",") | map( {(.): $in[.]} ) | add'
输出:
{"a":1,"b":10}