【问题标题】:using grep commands to find a duplicate id within a json file使用 grep 命令在 json 文件中查找重复的 id
【发布时间】:2021-02-22 16:50:14
【问题描述】:

我正在寻找一种在 linux 服务器上使用 grep 来查找重复的 json 记录的方法,是否可以在下面的示例中使用 grep 来搜索重复的 id?

所以 grep 会返回:01

{
 "book": [

  {
     "id": "01",
     "language": "Java",
     "edition": "third",
     "author": "Herbert Schildt"
  },
  {
     "id": "02",
     "language": "Java",
     "edition": "third",
     "author": "Herbert Schildt"
  },
  {
     "id": "03",
     "language": "Java",
     "edition": "third",
     "author": "Herbert Schildt"
  },
  {
     "id": "01",
     "language": "Java",
     "edition": "third",
     "author": "Herbert Schildt"
  },

  {
     "id": "04",
     "language": "C++",
     "edition": "second",
     "author": "E.Balagurusamy"
  }

 ]
}

【问题讨论】:

  • 跟进您对 Barmar 的回答的评论:那么您如何提供实际格式?

标签: linux shell command-line grep


【解决方案1】:

grepuniq 一起使用。

grep '"id":' filename | sort | uniq -d

-d 选项仅打印重复项。

但是,这取决于 JSON 布局是否整齐。要处理更一般的格式,我建议您使用jq 实用程序。

【讨论】:

  • 这假设 JSON 是定期布局的,所有 id 字段的格式相同,单独一行。
  • @Barmar 在上面的示例 JSON 中这有效,但是在我的实际 JSON 中它没有,我认为这是提到的格式问题,我将无法在服务器上安装任何其他工具。
【解决方案2】:

好的,如果awk 是可接受的,我可以从 JSON 字符串中丢弃任何空格 - hutch 是文件中上述 JSON 的格式化块。

我使用tr 删除任何空格,使用, 作为awk 中的字段分隔符;使用 for 循环遍历一个长行元素,在 awk 中进行一些模式匹配以隔离 ID 字段并为每个匹配的 ID 增加一个数组。在处理结束时,我遍历数组并打印具有多个匹配项的 ID。

这里是你的数据:

$ cat hutch 
{
 "book": [

  {
     "id": "01",
     "language": "Java",
     "edition": "third",
     "author": "Herbert Schildt"
  },
  {
     "id": "02",
     "language": "Java",
     "edition": "third",
     "author": "Herbert Schildt"
  },
  {
     "id": "03",
     "language": "Java",
     "edition": "third",
     "author": "Herbert Schildt"
  },
  {
     "id": "01",
     "language": "Java",
     "edition": "third",
     "author": "Herbert Schildt"
  },

  {
     "id": "04",
     "language": "C++",
     "edition": "second",
     "author": "E.Balagurusamy"
  }

 ]
}

这里发现了骗子:

$ tr -d '[:space:]' <hutch |  awk -F, '{for(i=1;i<=NF;i++){if($i~/"id":/){a[gensub(/^.*"id":"([0-9]+)"$/, "\\1","1",$i)]++}}}END{for(i in a){if(a[i]>1){print i}}}'
01

【讨论】:

    【解决方案3】:

    使用 Perl 单行来提取数字 ID,然后 sort | uniq -d 仅打印重复项(如 Barmar 的回答):

    这假设 id 键/值对位于同一行,但忽略行中任何位置(前导、尾随和中间)的空格(或缺少空格):

    perl -lne 'print for /"id":\s*"(\d+)"/' in.json | sort | uniq -d
    

    这不做任何假设(忽略空格和换行符)。请注意,它将整个 json 文件读入内存(使用-0777 命令行开关):

    perl -0777 -nE 'say for /"id":\s*"(\d+)"/g' in.json | sort | uniq -d
    

    Perl 单行程序使用这些命令行标志:
    -e:告诉 Perl 查找内联代码,而不是在文件中。
    -E:告诉 Perl 查找代码内联,而不是在文件中。还启用所有可选功能。在这里,启用say
    -n:一次循环输入一行,默认将其分配给$_
    -l:剥离输入行分隔符("\n" on *NIX 默认情况下)在内联执行代码之前,并在打印时附加它。
    -0777 : Slurp 整个文件。

    正则表达式使用此修饰符:
    /g:多个匹配项。

    另请参阅:
    perldoc perlrun: how to execute the Perl interpreter: command line switches
    perldoc perlre: Perl regular expressions (regexes)
    perldoc perlre: Perl regular expressions (regexes): Quantifiers; Character Classes and other Special Escapes; Assertions; Capture groups
    perldoc perlrequick: Perl regular expressions quick start

    【讨论】:

      【解决方案4】:

      基于jq 的方法:

      jq -r '.book[].id' < in.json | sort | uniq -d
      01
      

      即使对于没有换行符的缩小 JSON 文件,这也应该有效。

      【讨论】:

        猜你喜欢
        • 2011-08-07
        • 2020-01-24
        • 2017-06-06
        • 1970-01-01
        • 2013-10-20
        • 2018-03-28
        • 1970-01-01
        • 1970-01-01
        • 2015-06-28
        相关资源
        最近更新 更多