Вопрос или проблема
В 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
, что является содержимым тега.
Важные замечания
- Неподходящий выбор инструмента: Стоит отметить, что
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
, сохраняя при этом структуру документа и устойчивость к изменениям.
- Проблемы с масштабируемостью: Если ваш файл XML содержит много тегов или имеет сложную структуру, использование
grep
может привести к неожиданным результатам.
Заключение
Использование команды grep
для извлечения содержимого тега возможно благодаря поддержке регулярных выражений. Однако из-за ограничений grep
в разборе XML, рекомендуется использовать инструменты, разработанные специально для этой цели. Это обеспечит более корректное и надежное извлечение данных в долгосрочной перспективе.