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

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

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

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

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

Я пытался

grep -Gril MAIL_* .
grep -Grio MAIL_* .
grep -Gro MAIL_* .
13
задан TRiG 5 November 2014 в 11:46
поделиться

4 ответа

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

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

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

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

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

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

$ echo "Some garbage MAIL_OPTION comes MAIL_VALUE here" | grep -Eho 'MAIL_[^[:space:]]*'
MAIL_OPTION
MAIL_VALUE
17
ответ дан 1 December 2019 в 21:36
поделиться
grep -o or --only-matching

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

2
ответ дан 1 December 2019 в 21:36
поделиться

Попробуйте следующую команду

grep -Eo 'MAIL_[[:alnum:]_]*'
6
ответ дан 1 December 2019 в 21:36
поделиться

Из вашего комментария к ответу Тора следует, что вы также хотите различать, является ли текст MAIL_.* текстовым узлом или атрибутом, а не просто изолировать его всякий раз, когда он появляется в 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, которое выбирает все атрибуты в документе и затем @* выводит их значение
0
ответ дан 1 December 2019 в 21:36
поделиться
Другие вопросы по тегам:

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