grep может произвести только указанные группировки то соответствие?

Как условно сделать что-то если команда, за которой следуют или неудавшийся

Это точно что удар if оператор делает:

if command ; then
    echo "Command succeeded"
else
    echo "Command failed"
fi

Добавление информации из комментариев: Вы не должны использовать [ ... ] синтаксис в этом случае. [ самостоятельно команда, очень почти эквивалентная test. Это - вероятно, наиболее распространенная команда для использования в if, который может привести к предположению, что это - часть синтаксиса оболочки. Но если Вы хотите протестировать, ли команда, за которой следуют или нет, используйте саму команду непосредственно с if, как показано выше.

321
20.05.2011, 02:17
7 ответов

GNU grep имеет -P опция для perl-стиля regexes, и -o опция распечатать только, что соответствует шаблону. Они могут быть объединены с помощью, осматривают утверждения (описанный под Расширенными Шаблонами в perlre странице справочника) для удаления части grep шаблона от того, что полно решимости соответствовать в целях -o.

$ grep -oP 'foobar \K\w+' test.txt
bash
happy
$

\K краткая форма (и более эффективная форма) (?<=pattern) который Вы используете в качестве нулевой ширины, оглядываются утверждение перед текстом, который Вы хотите произвести. (?=pattern) может использоваться в качестве утверждения предвидения нулевой ширины после текста, который Вы хотите произвести.

Например, если Вы хотели распознать слово между foo и bar, Вы могли использовать:

$ grep -oP 'foo \K\w+(?= bar)' test.txt

или (для симметрии)

$ grep -oP '(?<=foo )\w+(?= bar)' test.txt
351
27.01.2020, 19:26
  • 1
    Как Вы делаете это, если Ваш regex имеет больше, чем группировка? (поскольку заголовок подразумевается?) –  barracel 21.03.2013, 09:52
  • 2
    @barracel: Я не полагаю, что Вы можете. Время для sed(1) –  camh 23.03.2013, 00:51
  • 3
    @camh я только что протестировал это grep -oP 'foobar \K\w+' test.txt ничего не производит с OP's test.txt. grep версия 2.5.1. Что могло быть неправильным? O_O –  SOUser 24.07.2014, 17:19
  • 4
    @XichenLi: Я не могу сказать. Я просто создал v2.5.1 grep (это довольно старо - с 2006), и он работал на меня. интерфейс –  camh 25.07.2014, 13:18
  • 5
    @SOUser: Я испытал то же - ничего не производит в файл. Я отправил запрос редактирования для включения'>' перед именем файла для отправки вывода, поскольку это работало на меня. –  rjchicago 15.12.2016, 23:40

Стандарт grep не может сделать, это, но последние версии GNU grep может. Можно обратиться к sed, awk или жемчугу. Вот несколько примеров, которые делают то, что Вы хотите на своем демонстрационном входе; они ведут себя немного по-другому в угловых случаях.

Замена foobar word other stuff word, распечатайте, только если замена сделана.

sed -n -e 's/^foobar \([[:alnum:]]\+\).*/\1/p'

Если первое слово foobar, распечатайте второе слово.

awk '$1 == "foobar" {print $2}'

Полоса foobar если это - первое слово, и пропустите строку иначе; затем разделите все после первого пробела и печати.

perl -lne 's/^foobar\s+// or next; s/\s.*//; print'
45
27.01.2020, 19:26
  • 1
    Потрясающий! Я думал I, могут делать это с sed, но я не использовал его прежде, и надеялся, что я мог использовать свое знакомое grep. Но синтаксис для этих команд на самом деле выглядит очень знакомым теперь, когда я знаком с поиском стиля энергии и заменой + regexes. Благодарит тонну. –  Cory Klein 20.05.2011, 02:51
  • 2
    , Не верной, Gilles. См. мой ответ для GNU grep решение. –  camh 20.05.2011, 04:33
  • 3
    @camh: А-ч, я не знал, что GNU grep теперь имел полную поддержку PCRE. Я исправил свой ответ, спасибо. взгляд –  Gilles 'SO- stop being evil' 20.05.2011, 10:14
  • 4
    Этот ответ особенно полезен для встроенного Linux начиная с Busybox grep не имеет поддержки PCRE. –  Craig McQueen 17.03.2016, 02:12

Ну, если Вы знаете, что foobar всегда является первым словом или строкой, затем можно использовать сокращение. Как так:

grep "foobar" test.file | cut -d" " -f2
19
27.01.2020, 19:26
  • 1
    -o включите grep, широко реализован (moreso, чем Гну grep расширения), таким образом делая grep -o "foobar" test.file | cut -d" " -f2 увеличит эффективность этого решения, которое является более портативным, чем использование lookbehind утверждения. –  dubiousjim 20.04.2012, 00:04
  • 2
    я полагаю, что Вам было бы нужно grep -o "foobar .*"или grep -o "foobar \w+". –  G-Man Says 'Reinstate Monica' 14.04.2018, 10:20

Если PCRE не поддерживается, можно достигнуть того же результата с двумя вызовами grep. Например, для захвата слова после того, как foobar делают это:

<test.txt grep -o 'foobar  *[^ ]*' | grep -o '[^ ]*$'

Это может быть расширено до произвольного слова после foobar как это (с EREs для удобочитаемости):

i=1
<test.txt egrep -o 'foobar +([^ ]+ +){'$i'}[^ ]+' | grep -o '[^ ]*$'

Вывод:

1

Отметьте индекс i основано на нуле.

9
27.01.2020, 19:26
    sed -n "s/^.*foobar\s*\(\S*\).*$/\1/p"

-n     suppress printing
s      substitute
^.*    anything before foobar
foobar initial search match
\s*    any white space character (space)
\(     start capture group
\S*    capture any non-white space character (word)
\)     end capture group
.*$    anything after the capture group
\1     substitute everything with the 1st capture group
p      print it
41
27.01.2020, 19:26

pcregrepимеет более умный вариант -oкоторый позволяет вам выбрать, какие группы захвата вы хотите вывести. Итак, используя ваш файл примера,

$ pcregrep -o1 "foobar (\w+)" test.txt
bash
happy
25
27.01.2020, 19:26

Мне очень помог ответ @jgshawkey. grepне такой уж хороший инструмент для этого, но sed подойдет, хотя здесь у нас есть пример, который использует grep для захвата соответствующей строки.

Синтаксис sed в регулярных выражениях уникален, если вы к нему не привыкли.

Вот еще один пример :этот анализирует вывод xinput для получения целочисленного идентификатора

⎜   ↳ SynPS/2 Synaptics TouchPad                id=19   [slave  pointer  (2)]

а я хочу 19

export TouchPadID=$(xinput | grep 'TouchPad' | sed  -n "s/^.*id=\([[:digit:]]\+\).*$/\1/p")

Обратите внимание на синтаксис класса:

[[:digit:]]

и необходимость избежать следующего+

Я предполагаю, что совпадает только одна строка.

3
27.01.2020, 19:26

Теги

Похожие вопросы