You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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"}

问题解答

  1. 这是zsh的已知行为吗?
    是。核心差异在于zsh的echo默认会解析转义序列,而bash的echo默认不解析。子shell捕获输出时,两个shell的变量捕获逻辑一致,但后续用echo输出变量时,zsh的echo会把字符串中的\\n转成\n,把\n转成真实换行,导致最终显示不同。

  2. 这是jq的Bug吗?
    不是。jq的行为完全符合预期:

  • 当传入的是字面量\n(即字符\加n),jq会按照JSON格式要求转义为\\n;
  • 当传入的是真实换行符,jq会输出JSON标准的换行转义符\n。
    所有差异都来自shell的echo和变量处理逻辑,和jq无关。
  1. 还是本就如此设计,我有所遗漏?
    是设计如此。你遗漏了不同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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.17 17:52:12