Скажи, у меня есть файл:
# file: 'test.txt'
foobar bash 1
bash
foobar happy
foobar
Я только хочу знать, какие слова появляются после "foobar", поэтому я могу использовать это регулярное выражение:
"foobar \(\w\+\)"
Скобки указывают, что у меня есть особый интерес к слову сразу после foobar. Но когда я делаю a grep "foobar \(\w\+\)" test.txt
, я получаю целые строки, которые соответствуют всему регулярному выражению, а не просто «слово после foobar»:
foobar bash 1
foobar happy
Я бы предпочел, чтобы выходные данные этой команды выглядели так:
bash
happy
Есть ли способ сказать grep выводить только элементы, которые соответствуют группировке (или определенной группировке) в регулярном выражении?
text-processing
grep
regular-expression
Кори Кляйн
источник
источник
perl -lne 'print $1 if /foobar (\w+)/' < test.txt
Ответы:
GNU grep имеет
-P
опцию для регулярных выражений в стиле Perl и-o
возможность печатать только то, что соответствует шаблону. Их можно объединить с помощью проверочных утверждений (описанных в разделе « Расширенные шаблоны» на man-странице perlre ), чтобы удалить часть шаблона grep из того, что определено для соответствия-o
.Это
\K
краткая форма (и более эффективная форма),(?<=pattern)
которую вы используете как предварительное утверждение нулевой ширины перед текстом, который вы хотите вывести.(?=pattern)
может использоваться как упреждающее утверждение нулевой ширины после текста, который вы хотите вывести.Например, если вы хотите сопоставить слово между
foo
иbar
, вы можете использовать:или (для симметрии)
источник
sed(1)
grep -oP 'foobar \K\w+' test.txt
ничего не дает с OPtest.txt
. Версия grep 2.5.1. Что может быть не так? O_OСтандартный grep не может этого сделать, но последние версии GNU grep могут . Вы можете обратиться к sed, awk или perl. Вот несколько примеров, которые делают то, что вы хотите на вашем примере ввода; они ведут себя немного по-другому в угловых случаях.
Заменить
foobar word other stuff
наword
, печатать только после замены.Если первое слово есть
foobar
, выведите второе слово.Раздень,
foobar
если это первое слово, и пропусти строку в противном случае; затем удалите все после первого пробела и напечатайте.источник
grep
. Но синтаксис этих команд на самом деле выглядит очень знакомым теперь, когда я знаком с поиском и заменой в стиле vim. Благодаря тонну.grep
не имеет поддержки PCRE.источник
^
и$
посторонние, так.*
как это жадный матч. Однако включение их может помочь прояснить намерение регулярного выражения.Ну, если вы знаете, что foobar - это всегда первое слово или строка, тогда вы можете использовать cut. Вот так:
источник
-o
Переключатель на Grep широко применяется ( в большей степени , чем расширений Grep Gnu), тем самымgrep -o "foobar" test.file | cut -d" " -f2
повысит эффективность этого решения, которое является более компактен , чем с помощью утверждений касательно предшествующего текста.grep -o "foobar .*
"илиgrep -o "foobar \w+"
.Если PCRE не поддерживается, вы можете достичь того же результата с помощью двух вызовов grep. Например, чтобы взять слово после foobar, сделайте так:
Это может быть расширено до произвольного слова после foobar следующим образом (с ERE для удобства чтения):
Выход:
Обратите внимание, что индекс начинается с
i
нуля.источник
pcregrep
имеет более умную-o
опцию, которая позволяет вам выбрать, какие группы захвата вы хотите выводить. Итак, используя ваш файл примера,источник
Использование
grep
не является кросс-платформенным, так как-P
/--perl-regexp
доступно только в GNUgrep
, но не в BSDgrep
.Вот решение с использованием
ripgrep
:Согласно
man rg
:Похожие: GH-462 .
источник
Я нашел ответ @jgshawkey очень полезным.
grep
это не очень хороший инструмент для этого, но sed есть, хотя здесь у нас есть пример, который использует grep для захвата соответствующей строки.Синтаксис регулярного выражения sed уникален, если вы к нему не привыкли.
Вот еще один пример: этот анализирует вывод xinput, чтобы получить целое число идентификатора
и я хочу 19
Обратите внимание на синтаксис класса:
и необходимость избежать следующего
+
Я предполагаю, что только одна строка соответствует.
источник
grep
, предполагая, что TouchPad находится слева от id:echo "SynPS/2 Synaptics TouchPad id=19 [slave pointer (2)]" | sed -nE "s/.*TouchPad.+id=([0-9]+).*/\1/p"