В grep на Ubuntu, как я могу отобразить только строку, которая соответствует регулярному выражению?

Я в основном grepping с регулярным выражением. В выходных данных я хотел бы видеть только строки, соответствующие моему reg exp.

в куче XML-файлов (в основном это однострочные файлы с огромным количеством данных в строке), я хотел бы получить все слова, которые начинаются с MAIL_.

кроме того, я хотел бы, чтобы команда grep в оболочке давала только слова, которые совпадают, а не всю строку (которая является всем файлом в этом случай.)

Как это сделать?

Я пробовал

grep -Gril MAIL_* .
grep -Grio MAIL_* .
grep -Gro MAIL_* .

4 ответов


прежде всего, с GNU grep, который установлен с Ubuntu, флаг-G (использовать базовое регулярное выражение) по умолчанию, поэтому вы можете опустить его, но, еще лучше, использовать расширенное регулярное выражение с-E.

-Р флаг означает рекурсивный поиск в файлах каталога, это то, что вам нужно.

и вы можете использовать флаг-o для печати соответствующей части строки. Кроме того, чтобы опустить имена файлов, вам понадобится флаг a-h.

единственная ошибка, которую вы сделали, - это регулярное выражение. Вы пропущенная спецификация символов перед *. Ваша команда должна выглядеть так:

grep -Ehro 'MAIL_[^[:space:]]*' .

пример вывода (не рекурсивный):

$ echo "Some garbage MAIL_OPTION comes MAIL_VALUE here" | grep -Eho 'MAIL_[^[:space:]]*'
MAIL_OPTION
MAIL_VALUE

попробуйте выполнить следующую команду

grep -Eo 'MAIL_[[:alnum:]_]*'

grep -o or --only-matching

выводит только соответствующий текст вместо полных строк, но проблема может быть в вашем регулярном выражении, которое не является ограничительным или достаточно жадным и фактически соответствует всему файлу.


из вашего комментария к ответу Тора кажется, что вы также хотите отличить, если MAIL_.* text-это текстовый узел или атрибут, а не просто изолировать его всякий раз, когда он появляется в XML-документе. Grep не может анализировать XML,тебе нужен парсер XML для этого.

синтаксический анализатор xml командной строки -xmlstarlet. Он упакован в Ubuntu.

используя его в этом примере файла пример файла:

$ cat test.xml 
<some_root>
    <test a="MAIL_as_attribute">will be printed if you want matching attributes</test>
    <bar>MAIL_as_text will be printed if you want matching text nodes</bar>
    <MAIL_will_not_be_printed>abc</MAIL_will_not_be_printed>
</some_root>

для выбора текстовых узлов вы можете использовать:

$ xmlstarlet sel -t -m '//*' -v 'text()' -n test.xml | grep -Eo 'MAIL_[^[:space:]]*'
MAIL_as_text

и для выбора атрибутов:

$ xmlstarlet sel -t -m '//*[@*]' -v '@*' -n test.xml | grep -Eo 'MAIL_[^[:space:]]*'
MAIL_as_attribute

краткое описание:

  • //* - это выражение XPath, которое выбирает все элементы в документе и text() выводит значение своих дочерних текстовых узлов, поэтому все, кроме текстовых узлов, фильтруется
  • //*[@*] - это выражение XPath, которое выбирает все атрибуты в документе, а затем @* выводит их стоимостью