grep: групповой захват - PullRequest
       3

grep: групповой захват

49 голосов
/ 22 декабря 2011

У меня есть следующая строка:

{"_id":"scheme_version","_rev":"4-cad1842a7646b4497066e09c3788e724","scheme_version":1234}

и мне нужно получить значение «версии схемы», которое в этом примере составляет 1234.

Я пытался

grep -Eo "\"scheme_version\":(\w*)"

однако возвращается

"scheme_version":1234

Как я могу это сделать? Я знаю, что могу добавить sed call, но я бы предпочел сделать это с одним grep.

Ответы [ 6 ]

60 голосов
/ 22 декабря 2011

Вам нужно будет использовать утверждение позади, чтобы оно не было включено в матч:

grep -Po '(?<=scheme_version":)[0-9]+'

49 голосов
/ 22 декабря 2011

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

echo '{"_id":"scheme_version","_rev":"4-cad1842a7646b4497066e09c3788e724","scheme_version":1234}' |
sed -n 's/.*"scheme_version":\([^}]*\)}/\1/p'
1234

Извините, это не grep , поэтому не обращайте внимания на это решение, если хотите.

Или придерживайтесь grep и добавьте:

grep -Eo "\"scheme_version\":(\w*)"| cut -d: -f2
37 голосов
/ 28 января 2014

Я бы порекомендовал вам использовать jq для работы. jq - это процессор JSON для командной строки.

$ cat tmp
{"_id":"scheme_version","_rev":"4-cad1842a7646b4497066e09c3788e724","scheme_version":1234}

$ cat tmp | jq .scheme_version
1234
23 голосов
/ 17 декабря 2016

В качестве альтернативы методу положительного просмотра, предложенному SiegeX, вы можете сбросить начальную точку совпадения сразу после scheme_version": с помощью escape-последовательности \K.Например,

$ grep -Po 'scheme_version":\K[0-9]+'

Это перезапускает процесс сопоставления после сопоставления scheme_version": и имеет тенденцию иметь гораздо лучшую производительность, чем положительный взгляд назад.Сравнение двух в regexp101 показывает, что метод запуска сброса совпадений занимает 37 шагов и 1 мс, а метод положительного просмотра - 194 шага и 21 мс.

Вы можете сами сравнить производительность на regex101 иВы можете прочитать больше о сбросе начальной точки в документации PCRE .

5 голосов
/ 16 апреля 2018

Чтобы не использовать функцию PCRE grep s, которая доступна в GNU grep, но не в BSD версии , другой метод заключается в использовании ripgrep , например

$ rg -o 'scheme_version.?:(\d+)' -r '$1' <file.json 
1234

-r Индексы захвата группы (например, $5) и имена (например, $foo).

Другой пример с Python и json.tool модулем , который может проверять и печатать:

$ python -mjson.tool file.json | rg -o 'scheme_version[^\d]+(\d+)' -r '$1'
1234

Related: Может ли grep выводить только указанные группы, которые соответствуют?

1 голос
/ 07 декабря 2015

Вы можете сделать это:

$ echo '{"_id":"scheme_version","_rev":"4-cad1842a7646b4497066e09c3788e724","scheme_version":1234}' | awk -F ':' '{print $4}' | tr -d '}'
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...