【问题标题】:converting lines to json in bash在bash中将行转换为json
【发布时间】:2014-10-09 20:10:05
【问题描述】:

我想将列表转换为 JSON 数组。我正在为此查看jq,但这些示例主要是关于解析 JSON(而不是创建它)。很高兴知道会发生正确的转义。我的列表是单行元素,所以新行可能是最好的分隔符。

【问题讨论】:

  • 顺便说一句,-1 不是我,但如果我不得不猜测它为什么在那里,它可能是“请为我工作”的气味(否则有用且值得,因此我的回答)问题就解决了。展示您的工作和遇到的问题,尝试自己解决这个问题可以避免这种情况。
  • 谢谢你,是的,我用谷歌搜索了一下。我正在寻找一个小的单行字,这可能是我在jq 手册页中遗漏的东西。感谢您的反馈,赞成票是我。

标签: bash jq


【解决方案1】:

我还试图将一堆行转换为 JSON 数组,并且一直处于停顿状态,直到我意识到 -s 是我在 jq 表达式中一次可以处理多行的唯一方法,即使这意味着我必须手动解析换行符。

jq -R -s -c 'split("\n")' < just_lines.txt
  • -R 读取原始输入
  • -s 将所有输入读取为单个字符串
  • -c 不漂亮地打印输出

简单易懂。

编辑:我在 jq ≥ 1.4,显然是在引入 split 内置时。

【讨论】:

  • 看起来很简单..虽然我无法验证。我在 ubuntu jq 版本 1.3 error: split is not defined 上遇到错误
  • 不幸的是,jq 文档没有说明每个内置函数的引入时间,jq --version 也没有告诉我我有什么版本,但它至少是 1.4,安装brew install jq --HEAD。不过,好点,我会编辑答案。
  • 我喜欢这个答案,除了对于具有尾随换行符(\n)的多行输出,split 内置函数将在数组中产生一个额外的空字符串项:(无论如何要解决这个问题?
  • 我目前的技巧是将其重新传送到jq 以使用其切片功能¯_(ツ)_/¯ echo $(jq -R -s -c 'split("\n")' &lt; urls.txt) | jq '.[:-1]'
  • 考虑'split("\n") | map(select(length &gt; 0))' 也删除空行。
【解决方案2】:

--raw-input,然后--slurp

只是以一种希望更快理解的形式总结其他人所说的话:

cat /etc/hosts  | jq  --raw-input .  | jq --slurp .

会还给你:

[
  "fe00::0 ip6-localnet",
  "ff00::0 ip6-mcastprefix",
  "ff02::1 ip6-allnodes",
  "ff02::2 ip6-allrouters"
]

说明

 --raw-input/-R:

       Don´t parse the input as JSON. Instead, each line of text is passed
       to  the  filter  as  a  string.  If combined with --slurp, then the
       entire input is passed to the filter as a single long string.

 --slurp/-s:

       Instead of running the filter for each JSON object  in  the  input,
       read  the entire input stream into a large array and run the filter
       just once.

【讨论】:

    【解决方案3】:

    您还可以使用jq -R . 将每一行格式化为 JSON 字符串,然后在将输入行解析为 JSON 后使用jq -s (--slurp) 为输入行创建一个数组:

    $ printf %s\\n aa bb|jq -R .|jq -s .
    [
      "aa",
      "bb"
    ]
    

    如果输入以换行符结尾,chbrown 的答案中的方法会在末尾添加一个空元素,但您可以使用printf %s "$(cat)" 删除尾随换行符:

    $ printf %s\\n aa bb|jq -R -s 'split("\n")'
    [
      "aa",
      "bb",
      ""
    ]
    $ printf %s\\n aa bb|printf %s "$(cat)"|jq -R -s 'split("\n")'
    [
      "aa",
      "bb"
    ]
    

    如果输入行不包含 ASCII 控制字符(必须在有效 JSON 的字符串中转义),您可以使用 sed:

    $ printf %s\\n aa bb|sed 's/["\]/\\&/g;s/.*/"&"/;1s/^/[/;$s/$/]/;$!s/$/,/'
    ["aa",
    "bb"]
    

    【讨论】:

    • jqjq 的管道不需要漂亮的打印:jq -cR . | jq -s .
    • 与其在单独的调用中啜饮输入,不如将原始输入放入数组中。 jq -Rn '[inputs]' input.json。这些都是等价的:jq -s '.' input.jsonjq -n '[inputs]' input.json
    【解决方案4】:

    更新:如果你的 jq 有 inputs 你可以简单地写:

    jq -nR [inputs] /etc/hosts 
    

    生成一个 JSON 字符串数组。这样可以避免读取整个文本文件。

    【讨论】:

    • 添加 -n 使其不会跳过第一行 - 它避免单独使用第一个输入。
    【解决方案5】:

    我在 jq 的手册页中发现了一个在我看来是一个更简单的答案。

    $ cat test_file.txt | jq -Rsc '. / "\n" - [""]'
    ["aa","bb"]
    

    -R 是在不尝试解析 json 的情况下读取,-s 表示将所有输入作为一个字符串读取,-c 用于单行输出 - 不是必需的,但这是我正在寻找的.

    然后在我传递给 jq 的字符串中,'.'说按原样输入。 '/ \n' 表示在换行符上划分字符串(拆分它)。 '- [""]' 表示要从结果数组中删除任何空字符串(由末尾的额外换行符产生)。

    这是一行,没有任何复杂的结构,只使用简单的内置 jq 功能。

    【讨论】:

      猜你喜欢
      • 2017-11-30
      • 2021-07-16
      • 1970-01-01
      • 2017-02-04
      • 1970-01-01
      • 2020-10-04
      • 2014-08-09
      • 2019-04-18
      • 2014-06-14
      相关资源
      最近更新 更多