Я работаю с файлами XML, каждый из которых может состоять из десятков строк. Буквально сотни этих файлов разбросаны по всей структуре каталогов. Да, это Мадженто.

Мне нужно найти файл с элементом <foo><bar><boom><bang>. Тег <boom><bang> может быть определен под другими тегами, поэтому мне нужно искать полный путь, а не только конечный тег или теги. Между каждым тегом и другими тегами между ними могут быть десятки строк:

<foo>
  <hello_world>
... 50 lines ....
  </hello_world>
  <bar>
    <giraffe>
... 50 lines ....
    </giraffe>
    <boom>
      <bang>Vital information here</bang>
    </boom>
  </bar>
</foo>

Какой элегантный способ *nix для поиска файла, который определяет <foo><bar><boom><bang>? В настоящее время я использую современный дистрибутив, производный от Debian.

Это мое текущее решение, которое далеко не красноречиво:

$ grep -rA 100 foo * | grep -A 100 bar | grep -A 100 boom | grep bang | grep -E 'foo|bar|boom|bang'
4
dotancohen 1 Авг 2021 в 17:39

2 ответа

Лучший ответ

Вы можете попробовать xmlstarlet заменить select i, если путь существует, а затем вывести fимя файла:

find . -name '*.xml' -exec xmlstarlet sel -t -i '/foo/bar/boom/bang' -f -n {} +
5
steeldriver 1 Авг 2021 в 18:27
Имейте в виду, что я новичок в xml/xmlstarlet, и с этим подходом могут быть проблемы...
 – 
steeldriver
1 Авг 2021 в 17:42
Конечно, но они гораздо менее ошибочны, чем мое текущее решение на основе grep. Если я улучшу это, я добавлю комментарий или отредактирую. Спасибо.
 – 
dotancohen
1 Авг 2021 в 17:52

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

find -type f -name '*.xml' -exec sh -c '
    xq -e '.foo.bar.boom.bang' "$1" >/dev/null
' _ {} \; -print

-e установить код состояния выхода на основе вывода;


Из man jq для получения более подробной информации об этой опции:

-e / --exit-status:
Устанавливает статус выхода jq в 0, если последние выходные значения не были ни ложными, ни нулевыми, 1, если последнее выходное значение было либо false, либо null, либо 4, если никогда не было получено действительного результата. Обычно jq завершается с 2, если возникла какая-либо проблема с использованием или системная ошибка, 3, если произошла ошибка компиляции программы jq, или 0, если программа jq запустилась.

3
αғsнιη 1 Авг 2021 в 21:27
Спасибо, xy кажется очень полезным инструментом! Я использовал jq в прошлом. Есть ли способ добавить подстановочные знаки в дерево элементов, например .foo.*.bang (пример, который не работает)? Погуглив, я не вижу простого решения, но если вы знаете навскидку, я был бы признателен. Спасибо.
 – 
dotancohen
2 Авг 2021 в 12:45
Я не очень хорошо разбираюсь в этих командах, просто немного знаю, в случаях, когда я вижу подобные вопросы, я собираюсь просмотреть их справочные страницы, чтобы узнать, есть ли там соответствующие вещи, которые могут решить вопрос спрашивающего или нет. Я не уверен, могут ли эти команды поддерживать подстановочные знаки или нет, но я знаю, что у них есть некоторые функции для сопоставления регулярных выражений, но я никогда их не использовал. вы также можете посмотреть там тоже. и добро пожаловать! кстати, это также xq, yq не xy.
 – 
αғsнιη
2 Авг 2021 в 14:32
Спасибо. Да, я проверил, прежде чем спрашивать, но лучшее, что я нашел, это сложный обходной путь для jq.
 – 
dotancohen
2 Авг 2021 в 15:11
См. также здесь stedolan.github.io/jq/manual/#RegularexpressionsPCRE для регулярного выражения сопоставление в jq, которое, я думаю, должно применяться и в xq (опять же не тестировалось и не использовалось раньше)
 – 
αғsнιη
2 Авг 2021 в 18:31