【问题标题】:How to use Unix command line utils to filter fields from a json record?如何使用 Unix 命令行工具从 json 记录中过滤字段?
【发布时间】:2014-04-18 12:50:55
【问题描述】:

我有一个包含许多 json 记录的文本文件,格式类似于以下内容:

{"foo":"1","bar":"2","baz":"1","fu":"1"}
{"foo":"3","bar":"2","baz":"4","fu":"2","barf":"1"}
{"foo":"2","bar":"4","baz":"5","fu":"3"}
{"foo":"5","blerg":"1","bar":"6","baz":"6","fu":"7"}

如何使用标准的 unix 命令行工具来过滤掉多个不相邻的字段?

例如。假设我只想选择 bar 和 fu,我希望我的输出看起来像:

"bar":"2" "fu":"1"

...或类似的东西。谢谢!

【问题讨论】:

  • 我看不出使用复杂的正则表达式来获取 JSON 解析器会立即得到的东西的意义。 grep 不适合这个,也许sed 更好。
  • 对几乎任何东西都开放 - 我仅限于几乎所有标准 CLI 工具

标签: json unix command-line grep


【解决方案1】:

使用sed,您可以这样做:

$ sed -r 's/.*("bar":"\w*").*("fu":"\w*").*/\1 \2/' file
"bar":"2" "fu":"1"
"bar":"2" "fu":"2"
"bar":"4" "fu":"3"
"bar":"6" "fu":"7"

如您所见,.*("bar":"\w*").*("fu":"\w*").* 捕获了"bar": "value""fu": "value" 的块,并使用\1\2 将它们打印回来。

【讨论】:

    【解决方案2】:

    这是awk 的简单工作

    awk -F"[{},]" '{print $3,$5}' file
    "bar":"2" "fu":"1"
    "bar":"2" "fu":"2"
    "bar":"4" "fu":"3"
    "bar":"6" "fu":"7"
    

    支持随机字段的awk

    awk -F, '{gsub(/[{}]/,x);for (i=1;i<=NF;i++) if ($i~/"foo"|"bar"/) printf "%s ",$i;print ""}' file
    "foo":"1" "bar":"2"
    "foo":"3" "bar":"2"
    "foo":"2" "bar":"4"
    "foo":"5" "bar":"6"
    

    【讨论】:

    • 这个问题应该更清楚 - 不幸的是,字段的数量是任意的
    【解决方案3】:

    如果json格式是固定的,你可以使用sedcut来过滤掉特定的列。例如,如果要过滤掉第 2 列和第 4 列,可以运行:

    $ cat output.txt | sed s/[{}]//g | cut -d, -f2,4 | sed s/,/" "/g
    

    如果你想更灵活,你可以用 proper 正则表达式运行 `sed 或编写一个 python 脚本,这会容易得多。

    更新:感谢您指出潜在的性能问题。无论如何,我投票支持awk 解决方案。

    $ sed s/[{}]//g output.txt | cut -d, -f2,4 | sed s/,/" "/g
    

    【讨论】:

    • 你不应该catdata 给其他可以读取数据的程序。 sed s/[{}]//g file | cut -d, -f2,4 | sed s/,/" "/g
    【解决方案4】:

    对于未来的人,我认为像 json 命令行工具这样的特定于 json 的解析器将是最干净的解决方案。自述文件页面的底部也有一些替代方案的参考

    【讨论】:

      猜你喜欢
      • 2021-03-01
      • 1970-01-01
      • 2014-08-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-06-25
      • 1970-01-01
      • 2017-09-07
      相关资源
      最近更新 更多