为啥我的 jq / read / echo 管道会删除反斜杠?

Posted

技术标签:

【中文标题】为啥我的 jq / read / echo 管道会删除反斜杠?【英文标题】:Why does my jq / read / echo pipeline remove backslashes?为什么我的 jq / read / echo 管道会删除反斜杠? 【发布时间】:2020-07-02 18:32:01 【问题描述】:

我正在尝试将一个大型 JSON 文件(约 4 个 Mio 元素)拆分为单独的文件(每个元素一个文件)。

文件有点像这样:


  "books": [
    
      "title": "Professional javascript - \"The best guide\"",
      "authors": [
        "Nicholas C. Zakas"
      ],
      "edition": 3,
      "year": 2011
    ,
    
      "title": "Professional JavaScript",
      "authors": [
        "Nicholas C.Zakas"
      ],
      "edition": 2,
      "year": 2009
    ,
    
      "title": "Professional Ajax",
      "authors": [
        "Nicholas C. Zakas",
        "Jeremy McPeak",
        "Joe Fawcett"
      ],
      "edition": 2,
      "year": 2008
    
  ]


要将每本书拆分为单独的文件,我使用以下命令:

cat books.json | jq -c -M '.books[]' | while read line; do echo $line > temp/$(date +%s%N).json; done

对于最后两项,一切正常,因为书名不包含任何引号。但是,在第一个中,\"" 替换,这导致 JSON 文件损坏,因为后续解析器 - 当然 - 将 " 解释为元素的边界。

我尝试使用jq -r,但没有帮助。

我使用的是 CentOS 7 自带的 jq 版本:

[root@machine]$ jq --version
jq-1.6

有什么建议吗?

【问题讨论】:

仅供参考,BashFAQ #1 中介绍了使用 while read 循环的最佳实践。虽然它与jq 没有太大区别,但最好改掉使用cat filename | ... 的习惯;一些程序(包括sorttail)在获得真实的、可查找的文件句柄而不是只能从前到后读取一次的 FIFO(又名管道)时可以运行得更快。 这能回答你的问题吗? sh read command eats slashes in input? Why do backslashes disappear when run through echo? 是另一个预先存在的候选副本(标题没有说清楚,但它是相同的 while read; do 错误)。 【参考方案1】:

你必须使用-r选项来read

while read -r line; do echo "$line" > temp/"$(date +%s%N)".json; done

它可以防止解释反斜杠转义。

你应该引用你的变量。

看看区别:

$ read var <<< 'quoted quotes: \"\"'
$ echo "$var"
quoted quotes: ""
$ read -r var <<< 'quoted quotes: \"\"'
$ echo "$var"
quoted quotes: \"\"

-rread 一起使用几乎总是您想要的,并且确实应该是默认行为。

【讨论】:

以上是关于为啥我的 jq / read / echo 管道会删除反斜杠?的主要内容,如果未能解决你的问题,请参考以下文章

为啥管道输入到“read”只有在输入“while read ...”结构时才有效? [复制]

为啥打开 mkfifo 管道时我的程序会挂起?

为啥我的输入通过管道发送到进程时会延迟?

如何在 shell 管道中使用`jq`?

为啥我的多阶段完整 yaml azure devops 管道在移动到模板时会中断?

为啥我的 (ubuntu 11.10 bash 4.2.10, x86_64 ) 命名管道会堵塞?