awk (или sed / grep), чтобы получить вхождения подстроки - PullRequest
1 голос
/ 11 апреля 2019

У меня есть строка json в переменной bash, которая выглядит примерно так:

{
    "items": [
      {
        "foo": null,
        "timestamp": 1553703000,
        "bar": 123
      },
      {
        "foo": null,
        "timestamp": 1553703200,
        "bar": 456
      },
      {
        "foo": null,
        "timestamp": 1553703400,
        "bar": 789
      }
    ]
}

Я хочу знать, сколько из этих timestamp с заданной даты и времени, поэтому, если у меня будет 1553703100, он вернет 2.

(Бонусные мнимые баллы, если вы можете получить мне только это число!)

В качестве шага к этому, я хочу получить только совпадения "timestamp": \d+, в строке, чтобы я мог просмотреть их в скрипте bash.

Я немного использовал sed и grep, но никогда не использовал awk, и из моего прочтения кажется, что это может быть лучшим решением для этой задачи.

Другая информация: - Json уже напечатан, как указано выше, поэтому временные метки всегда будут в отдельных строках. - Это для запуска в Cygwin, поэтому у меня есть awk / gawk, sed и grep / egrep, но, вероятно, нет других. - Может быть любое количество временных меток в JSON.

Ответы [ 3 ]

4 голосов
/ 11 апреля 2019

Вы не предоставили ожидаемый результат, так что это предположение, но это то, что вы пытаетесь сделать?

$ echo "$var" | jq '.items[].timestamp'
1553703000
1553703200
1553703400

или, может быть:

$ echo "$var" | jq '.items[].timestamp | select(. > 1553703100)'
1553703200
1553703400

или

$ echo "$var" | jq '[.items[].timestamp | select(. > 1553703100)] | length'
2

ВНИМАНИЕ: Я только учусь jq, так что, возможно, есть лучшие способы сделать это!

3 голосов
/ 11 апреля 2019

edit: у второго подхода, перечисленного ниже, есть серьезные проблемы, которые были очень любезно изложены @EdMorton. Я решил сохранить старый код в образовательных целях.

Избегать substr() и перехватить нулевую строку i:

$ awk -v dt=1553703100 '
  /timestamp/ && $2+0>dt {i++}
  END {print i+0}
' <<< "$var"

2

ВНИМАНИЕ: ПРОБЛЕМНЫЙ КОД

Здесь я использовал substr(string, index, [characters]), чтобы обрезать запятую на вашем втором поле. Регулярное выражение /timestamp/ не является сложным; это может быть улучшено, если ваш JSON станет более сложным.

$ awk -v dt=1553703100 '
  /timestamp/ && substr($2, 0, length($2)) > dt {i++} 
  END {print i}
' <<< "$var"

2
0 голосов
/ 11 апреля 2019

Вы также можете быстро внедрить решение python:

ввод :

$ cat data.json 
{
    "items": [
      {
        "foo": null,
        "timestamp": 1553703000,
        "bar": 123
      },
      {
        "foo": null,
        "timestamp": 1553703200,
        "bar": 456
      },
      {
        "foo": null,
        "timestamp": 1553703400,
        "bar": 789
      }
    ]
}

код :

$ cat extract_value2.py 
import json

tLimit = 1553703100
with open('data.json') as f:
    data = json.load(f)
    print([t['timestamp'] for t in data["items"] if t['timestamp'] > tLimit])

выход :

$ python extract_value2.py 
[1553703200, 1553703400]

код счета:

$ cat extract_value2.py 
import json

tLimit = 1553703100
with open('data.json') as f:
    data = json.load(f)
    print(len([t['timestamp'] for t in data["items"] if t['timestamp'] > tLimit]))

выход :

$ python extract_value2.py
2 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...