Удаление шаблона из нескольких строк с помощью sed или awk в двух местах в одной строке - PullRequest
0 голосов
/ 03 октября 2018

У меня есть файл JSON с 12 166 466 строк.Я хочу удалить кавычки из значений на ключах: "timestamp": "1538564256", и "score": "10",, чтобы они выглядели как "timestamp": 1538564256, и "score": 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
'

первая часть довольно проста, но как удалить ", при этом конец строки, который содержит" метку времени "и" счет "?Как получить доступ к этому с помощью sed или даже awk, или другого инструмента, имея в виду, что мне нужно обработать 12 миллионов строк?

Ответы [ 4 ]

0 голосов
/ 04 октября 2018

Это может сработать для вас (GNU sed):

sed ':a;/"timestamp":\s*"1538564256",/{s/"//3g;:b;n;/timestamp/ba;/"score":\s*"10"/s/"//3g;Tb}' file

При обнаружении строки, содержащей "timestamp": "1538564256",, удалите 3-й или более ".Затем продолжайте чтение до следующей строки, содержащей timestamp, и повторите или строку, содержащую "score": "10, и удалите 3-й или более ".

0 голосов
/ 03 октября 2018

Предполагая, что вы исправили свой входной файл 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"
  }
]

Вы можете использовать jq и его функцию tonumber, чтобы изменить нужные строки на значения:

<file jq '.[].timestamp |= tonumber | .[].score |= tonumber'
0 голосов
/ 03 октября 2018
  1. Имейте в виду, что tonumber может потерять точность.Если использование tonumber недопустимо, и если вывод производится с помощью jq (или иным образом линеаризуется по вертикали), то использование awk, как предложено в другом месте на этой странице, является хорошим способом.(Если в вашем awk нет gensub, то программу awk можно легко адаптировать.) Это то же самое, используя sed, предполагая, что его флаг для расширенной обработки регулярных выражений равен -E:

    sed -E -e 's/"(timestamp|score)": "([0-9]+)"/"\1": \2/'

  2. Для справки, если есть какие-либо сомнения относительно того, где находятся соответствующие ключи, вот фильтр в jq, который не зависит от этого:

    walk(if type == "object" then if has("timestamp") then .timestamp|=tonumber else . end | if has("score") then .score|=tonumber else end else . end)

Если у вашего jq нет walk/1, просто перехватите его определение из сети, например, из https://raw.githubusercontent.com/stedolan/jq/master/src/builtin.jq

Если вы хотите преобразовать все числовые строки в числа, вы можете написать:

walk(if type=="object" then map_values(tonumber? // .) else . end)

0 голосов
/ 03 октября 2018

Если структура JSON примерно соответствует вашему примеру (например, между "timestamp", двоеточием и значением не должно быть никаких других пробельных символов), тогда этот awk должен быть в порядке.Если возможно, лучше использовать jq для преобразования JSON!

awk '{print gensub(/("(timestamp|score)": )"([0-9]+)"/, "\\1\\3", "g")}' file
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...