如何在Ansible Shell任务中将set_fact设置的JSON变量传入jq管道?
解决Ansible中fact变量传入jq的解析错误问题
问题场景
已通过set_fact模块将JSON数据解析为变量data,但在通过shell模块调用jq转换格式时,出现Invalid numeric literal解析错误。
原剧本代码
- name: get data set_fact: data: "{{ value.stdout | from_json }}" - name: get key value pairs shell: echo "{{ data }}" | jq 'to_entries | map((.key) + "=" + .value)|join(",")' register: key_value
错误信息
TASK [utils : debug] ************************************************************************************* ok: [localhost] => { "data": { "key1": "keyval1", "key2": "keyval2" } } TASK [utils : get key value pairs] *************************************************************** FAILED! => {"changed": true, "cmd": "echo \"{'key1': 'keyval1', 'key2': 'keyval2'}\" | jq 'to_entries | map((.key) + \"=\" + .value)|join(\",\")'", "stderr": "parse error: Invalid numeric literal at line , column", "stderr_lines": ["parse error: Invalid numeric literal at line , column"], "stdout": "", "stdout_lines": []}
补充尝试
使用YAML折叠标量语法后仍报错:
- name: get key value pairs shell: > echo "{{ data }}" | jq 'to_entries | map((.key) + "=" + .value)|join(",")' register: key_value
错误原因
Ansible在渲染{{ data }}时,输出的是单引号包裹的Python字典格式(如{'key1': 'keyval1'}),而jq仅支持标准JSON格式(双引号包裹键和字符串值),因此触发解析错误。
解决方案
方案1:用to_json过滤器转换为标准JSON
在传递data给shell命令时,通过to_json过滤器将其转为符合JSON规范的字符串,让jq能正确解析:
- name: get key value pairs shell: echo "{{ data | to_json }}" | jq 'to_entries | map((.key) + "=" + .value)|join(",")' register: key_value
方案2:直接用Ansible过滤器完成转换(无需jq)
完全避开shell和jq,直接用Ansible内置的过滤器实现相同格式转换,更高效且避免跨环境问题:
- name: get key value pairs via ansible filters set_fact: key_value: "{{ data | dict2items | map('join', '=') | join(',') }}"
执行后key_value的值会是key1=keyval1,key2=keyval2,和预期的jq输出一致。
方案3:通过stdin传递变量(避免引号转义问题)
将data通过stdin传递给jq,减少命令行的引号转义风险:
- name: get key value pairs via stdin shell: jq 'to_entries | map((.key) + "=" + .value)|join(",")' args: stdin: "{{ data | to_json }}" register: key_value
内容的提问来源于stack exchange,提问作者Tiya Jose
相关产品推荐
相关产品推荐

