Как напечатать содержимое внутри тега, используя команду grep?

Вопрос или проблема

В Linux, как мы можем использовать команду grep для вывода содержимого, которое находится внутри этого тега?

<errorPayload>XXXXXXXX</errorPayload>

Я пытался использовать grep -Po '<errorPayload>' abc.log, но он выводит только <errorPayload>

Не используйте grep для разбора XML или HTML.

Вместо этого используйте правильный парсер:

xidel -s -e '//errorPayload/text()' file
XXXXXXXX

Также можно использовать xmllint и xmlstarlet:

xmlstarlet sel -t -v '//errorPayload/text()' file
xmllint --xpath '//errorPayload/text()' file

Он выводит только <errorPayload>, потому что вы сказали ему это сделать, используя опцию -o (--only-matching). Из справочной страницы, это означает “Выводить только совпадающие (непустые) части совпадающей строки…”

Если вы хотите увидеть только содержимое тега, вам нужно создать регулярное выражение, которое совпадает только с содержимым, но не с начальным/конечным тегом.

Это должно сработать:

grep -Po '(?<=<errorPayload>).*(?=</errorPayload>)' abc.log

С учетом вашего образца ввода в abc.log, это дает:

XXXXXXXX

Выражение (?<=<errorPayload>) — это “утверждение положительного смотрения назад”: оно означает, что данный шаблон должен совпадать перед нашим целевым выражением, но не считается частью “совпадающего содержимого”. Выражение (?=</errorPayload>) — это “утверждение положительного смотрения вперед”, которое делает то же самое, но для следующего шаблона.

Смотрите, например, эту статью для получения более подробной информации об утверждениях смотрения вперед и назад.


Предостережение: grep — это плохой инструмент для разбора XML. Вышеуказанное будет работать, пока форматирование XML в ваших лог-файлах последовательное.

Ответ или решение

Как напечатать содержимое тега с помощью команды grep

Использование утилиты grep для извлечения содержимого XML-тегов провоцирует определенные сложности и обычно не рекомендуется. Тем не менее, если вам нужно извлечь данные из тегов, таких как <errorPayload>, вы можете воспользоваться регулярными выражениями в grep. В этой статье мы рассмотрим, как это сделать, а также обсудим более подходящие инструменты для работы с XML.

Пример файла журнала

Предположим, у вас есть файл abc.log, содержащий следующие строки:

<errorPayload>XXXXXXXX</errorPayload>

Использование команды grep

Для того чтобы напечатать только содержимое тега <errorPayload>, вы можете использовать следующую команду:

grep -Po '(?<=<errorPayload>).*?(?=</errorPayload>)' abc.log

Разбор команды:

  • -P: Включает поддержку Perl-совместимых регулярных выражений.
  • -o: Печатает только совпадающие части строки.
  • (?<=<errorPayload>): Это положительное утверждение, убеждающее grep, что перед предполагаемым содержимым должно находиться <errorPayload>, но само это совпадение не будет включено в вывод.
  • .*?: Захватывает любое количество символов (включая ноль), что позволяет сопоставить содержимое тега.
  • (?=</errorPayload>): Положительное утверждение, обеспечивающее, что после содержимого должно находиться </errorPayload>.

Эта команда выведет XXXXXXXX, что является содержимым тега.

Важные замечания

  1. Неподходящий выбор инструмента: Стоит отметить, что grep не является оптимальным инструментом для разбора XML или HTML из-за своей ограничения по дополнительным атрибутам и ненормированному форматированию. Лучше использовать специализированные инструменты, такие как:
    • xmllint: Позволяет выполнять XPath-запросы.
    • xmlstarlet: Операции с XML через CLI.
    • xidel: Инструмент для извлечения данных с использованием CSS и XPath.

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

xmllint --xpath '//errorPayload/text()' abc.log
xmlstarlet sel -t -v '//errorPayload/text()' abc.log

Эти команды вернут XXXXXXXX, сохраняя при этом структуру документа и устойчивость к изменениям.

  1. Проблемы с масштабируемостью: Если ваш файл XML содержит много тегов или имеет сложную структуру, использование grep может привести к неожиданным результатам.

Заключение

Использование команды grep для извлечения содержимого тега возможно благодаря поддержке регулярных выражений. Однако из-за ограничений grep в разборе XML, рекомендуется использовать инструменты, разработанные специально для этой цели. Это обеспечит более корректное и надежное извлечение данных в долгосрочной перспективе.

Оцените материал
Добавить комментарий

Капча загружается...