bash与zsh及zsh子shell中jq换行处理的差异问题
bash与zsh中jq处理换行符的行为差异问题
我尝试用jq将字符串格式化为JSON时,发现bash和zsh存在行为差异:尤其是zsh中,直接运行jq和通过子shell运行后输出的结果不一样——输入的\n在前者输出为\\n,后者输出为\n。我有三个疑问:
- 这是zsh的已知行为吗?
- 这是jq的Bug吗?
- 还是本就如此设计,我有所遗漏?
另外,资料建议用printf %b获取真实换行而非字面量\n,这在bash中有效,但zsh两种运行模式的差异仍然存在。以下是测试案例:
$ jq --version jq-1.6 # --- # 直接使用 \n bash-3.2$ jq --null-input --compact-output --raw-output --monochrome-output --arg test 'A\nB' '{test: $test}' {"test":"A\\nB"} bash-3.2$ OUT=$(jq --null-input --compact-output --raw-output --monochrome-output --arg test 'A\nB' '{test: $test}'); echo $OUT {"test":"A\\nB"} zsh-5.8.1> jq --null-input --compact-output --raw-output --monochrome-output --arg test 'A\nB' '{test: $test}' {"test":"A\\nB"} zsh-5.8.1> OUT=$(jq --null-input --compact-output --raw-output --monochrome-output --arg test 'A\nB' '{test: $test}'); echo $OUT {"test":"A\nB"} # ----- # 使用 `printf %b` 转换 \n 为真实换行 bash-3.2$ jq --null-input --compact-output --raw-output --monochrome-output --arg test "$(printf %b 'A\nB')" '{test: $test}' {"test":"A\nB"} bash-3.2$ OUT=$(jq --null-input --compact-output --raw-output --monochrome-output --arg test "$(printf %b 'A\nB')" '{test: $test}'); echo $OUT {"test":"A\nB"} zsh-5.8.1> jq --null-input --compact-output --raw-output --monochrome-output --arg test "$(printf %b 'A\nB')" '{test: $test}' {"test":"A\nB"} zsh-5.8.1> OUT=$(jq --null-input --compact-output --raw-output --monochrome-output --arg test "$(printf %b 'A\nB')" '{test: $test}'); echo $OUT {"test":"A B"}
问题解答
这是zsh的已知行为吗?
是。核心差异在于zsh的echo默认会解析转义序列,而bash的echo默认不解析。子shell捕获输出时,两个shell的变量捕获逻辑一致,但后续用echo输出变量时,zsh的echo会把字符串中的\\n转成\n,把\n转成真实换行,导致最终显示不同。这是jq的Bug吗?
不是。jq的行为完全符合预期:
- 当传入的是字面量
\n(即字符\加n),jq会按照JSON格式要求转义为\\n; - 当传入的是真实换行符,jq会输出JSON标准的换行转义符
\n。
所有差异都来自shell的echo和变量处理逻辑,和jq无关。
- 还是本就如此设计,我有所遗漏?
是设计如此。你遗漏了不同shell中echo的默认行为差异:bash的echo默认不处理转义序列,而zsh的echo默认会处理。此外,当用子shell捕获输出后,变量中保存的是jq的原始输出,但echo的行为差异导致最终展示结果不同。
解决方案
如果要在zsh中保持和bash一致的输出,有两种方式:
- 使用
echo -E,禁用zshecho的转义解析功能:echo -E "$OUT" - 使用
printf输出变量,因为printf在bash和zsh中的行为更一致:printf '%s\n' "$OUT"
内容的提问来源于stack exchange,提问作者jakub.g
相关产品推荐
相关产品推荐

