Linux 在同一行的两个位置使用sed或awk从多行中删除模式

Linux 在同一行的两个位置使用sed或awk从多行中删除模式,linux,bash,awk,sed,jq,Linux,Bash,Awk,Sed,Jq,我有一个包含12166466行的JSON文件。 我想从键上的值中删除引号: “时间戳”:“1538564256”、和“分数”:“10”、看起来像 “时间戳”:1538564256,和“分数”:10, 输入: { "title": "DNS domain", , "timestamp": "1538564256", "domain": { "dns": [ "www.google.com" ] }, "

我有一个包含12166466行的JSON文件。 我想从键上的值中删除引号:
“时间戳”:“1538564256”、
“分数”:“10”、
看起来像
“时间戳”:1538564256,
“分数”:10,

输入:

{
    "title": "DNS domain", ,
    "timestamp": "1538564256",
    "domain": {
        "dns": [
            "www.google.com"
        ]
    },
    "score": "10",
    "link": "www.bit.ky/sdasd/asddsa"
    "id": "c-1eOWYB9XD0VZRJuWL6"
}, {
    "title": "DNS domain",
    "timestamp": "1538564256",
    "domain": {
        "dns": [
            "google.de"
        ]
    },
    "score": "10",
    "link": "www.bit.ky/sdasd/asddsa",
    "id": "du1eOWYB9XD0VZRJuWL6"
}
}
预期产出:

{
    "title": "DNS domain", ,
    "timestamp": 1538564256,
    "domain": {
        "dns": [
            "www.google.com"
        ]
    },
    "score": 10,
    "link": "www.bit.ky/sdasd/asddsa"
    "id": "c-1eOWYB9XD0VZRJuWL6"
}, {
    "title": "DNS domain",
    "timestamp": 1538564256,
    "domain": {
        "dns": [
            "google.de"
        ]
    },
    **"score": 10,**
    "link": "www.bit.ky/sdasd/asddsa",
    "id": "du1eOWYB9XD0VZRJuWL6"
}
}
我试过:

sed -E '
s/"timestamp": "/"timestamp": /g
s/"score": "/"score": /g
'

第一部分非常简单,但是如何删除“timestamp”和“score”行末尾的“?我如何使用sed、甚至awk或其他工具访问它,并记住我有1200万行要处理?

如果JSON结构与您的示例大致匹配(例如,
“timestamp”
、冒号和值之间不会有任何其他空白字符),那么这个awk应该是可以的。如果可用,使用
jq
进行JSON转换是目前最好的选择

awk '{print gensub(/("(timestamp|score)": )"([0-9]+)"/, "\\1\\3", "g")}' file

如果JSON结构与您的示例大致匹配(例如,
“timestamp”
、冒号和值之间不会有任何其他空格字符),那么这个awk应该是可以的。如果可用,使用
jq
进行JSON转换是目前为止更好的选择

awk '{print gensub(/("(timestamp|score)": )"([0-9]+)"/, "\\1\\3", "g")}' file

假设您按照以下方式修复JSON输入文件:

<file jq .
[
  {
    "title": "DNS domain",
    "timestamp": "1538564256",
    "domain": {
      "dns": [
        "www.google.com"
      ]
    },
    "score": "10",
    "link": "www.bit.ky/sdasd/asddsa",
    "id": "c-1eOWYB9XD0VZRJuWL6"
  },
  {
    "title": "DNS domain",
    "timestamp": "1538564256",
    "domain": {
      "dns": [
        "google.de"
      ]
    },
    "score": "10",
    "link": "www.bit.ky/sdasd/asddsa",
    "id": "du1eOWYB9XD0VZRJuWL6"
  }
]

假设您按照以下方式修复JSON输入文件:

<file jq .
[
  {
    "title": "DNS domain",
    "timestamp": "1538564256",
    "domain": {
      "dns": [
        "www.google.com"
      ]
    },
    "score": "10",
    "link": "www.bit.ky/sdasd/asddsa",
    "id": "c-1eOWYB9XD0VZRJuWL6"
  },
  {
    "title": "DNS domain",
    "timestamp": "1538564256",
    "domain": {
      "dns": [
        "google.de"
      ]
    },
    "score": "10",
    "link": "www.bit.ky/sdasd/asddsa",
    "id": "du1eOWYB9XD0VZRJuWL6"
  }
]
  • 请注意,
    tonumber
    可能会失去精度。如果使用
    tonumber
    是不允许的,并且如果输出是由jq生成的(或以其他方式垂直线性化),则按照本页其他地方的建议使用awk是一个很好的方法。(如果您的awk没有gensub,则可以轻松调整awk程序。)这里使用
    sed
    ,假设扩展正则表达式处理的标志是
    -E
    ,也是一样的:

    sed-E-E's/“(时间戳|分数)”:“([0-9]+)”/“\1:\2/”

  • 作为参考,如果对相关密钥的位置有任何疑问,jq中有一个过滤器对此不可知:

    walk(如果类型==“对象”
    如果有(“timestamp”),则.timestamp |=tonumber else.end
    |如果有(“分数”),则.score |=tonumber else end
    else.end)

  • 如果您的jq没有
    walk/1
    ,则只需从web(例如从

  • 如果要将所有数值字符串转换为数字,可以编写:

    walk(如果type==“object”,则映射值(tonumber?/)else.end)

  • 请注意,
    tonumber
    可能会失去精度。如果使用
    tonumber
    是不允许的,并且如果输出是由jq生成的(或以其他方式垂直线性化),则按照本页其他地方的建议使用awk是一个很好的方法。(如果您的awk没有gensub,则可以轻松调整awk程序。)这里使用
    sed
    ,假设扩展正则表达式处理的标志是
    -E
    ,也是一样的:

    sed-E-E's/“(时间戳|分数)”:“([0-9]+)”/“\1:\2/”

  • 作为参考,如果对相关密钥的位置有任何疑问,jq中有一个过滤器对此不可知:

    walk(如果类型==“对象”
    如果有(“timestamp”),则.timestamp |=tonumber else.end
    |如果有(“分数”),则.score |=tonumber else end
    else.end)

  • 如果您的jq没有
    walk/1
    ,则只需从web(例如从

  • 如果要将所有数值字符串转换为数字,可以编写:

    walk(如果type==“object”,则映射值(tonumber?/)else.end)

  • 这可能适用于您(GNU-sed):

    当遇到一行包含“时间戳”:“1538564256”时,删除第三行或更多的
    。然后继续阅读,直到另一行包含
    时间戳并重复,或者一行包含
    “分数”:“10
    并删除第三行或更多的

    这可能适合您(GNU-sed):


    遇到包含
    时间戳的行时:“1538564256”
    删除第三行或更多
    。然后继续阅读,直到另一行包含
    时间戳并重复,或一行包含
    “score”:“10
    并删除第三行或更多
    "

    没有使用sed或awk自己解析它,而是有一些JSON解析工具可以使用吗?JSON本身是使用JQ生成的。我相信没有办法告诉JQ不要对某些字段使用双引号。那怎么办?我会看看这个命令,我不知道它。我不会尝试类似的东西:
    sed-E's/:“([0-9]+)”/:\1/'file
    没有使用sed或awk自己解析它,你可能会使用一些JSON解析工具吗?JSON本身是使用JQ生成的。我相信没有办法告诉JQ不要对某些字段使用双引号。那怎么办?我会看看这个命令,我不知道它。我不会尝试这样的事情:
     sed-e的/:“([0-9]+)”/:\1/”文件
    我想你的意思是:
    awk'{print gensub(/“(timestamp | score)”:“([0-9]+)”/,“\“\\1\”:\\2”,“g”)}
    @peak哦,是的,我错过了
    timestamp | score
    周围的括号,谢谢!但我觉得直接否决有点苛刻:-(因为OP说JSON来自jq,我相信在这种情况下,用一个小的awk程序解析可以100%准确。如果你能准确地重新编写警告,我将向上投票:-)@peak好吧,看看JSON,它实际上在语法上是不正确的;-)(至少有三个错误)我想你的意思是:
    awk'{print gensub(/)(timestamp | score)“:”([0-9]+)“/,“\“\\1\”:\\2”,“g”)}
    @peak哦,是的,我错过了
    timestamp | score
    ,谢谢!但我发现直接下推有点苛刻:-(因为OP说JSON来自jq,我相信在这种情况下,用一个小awk程序解析可以100%准确)。