Рассматривали ли вы цикл по каждой категории? Вот так:
for i in *.xml; do
for category in $(sed -rn '/^/{s/[^>]*> *([^ <]*).*/\1/p}' "$i"); do
sed -rn "/^ *$category/,/^/{s/ *([^ <]*).*/\1/p}" "$i" > "$category.log"
done
done
awk -v 'RS=<' -v 'cat=none' -F '>' \
'$1 ~ /^category$/ {gsub(/^ *| *$/,"",$2); cat=$2} \
$1 ~ /^url$/ {print $2 >> cat".log"}' \
*.xml
Это позволяет избежать зацикливания входных файлов и добавит к файлу .log
любую категорию.
Использование назначения разделителя записей awk -v 'RS=<'
будет означать, что тег категории/url будет найден где угодно (, а не только в начале строки ). Новая строка может появиться в любом месте данных xml.
Сочетание этого с установкой разделителя полей на '>'
означает, что первое поле каждой записи будет эквивалентно имени тега xml.
Каждый раз, когда awk встречает запись, где первым полем является «категория», переменная cat
устанавливается на имя этой категории.
Когда awk встречает запись, где первым полем является «url», он добавит этот URL в файл cat.log
.
cat
будет определено как none
для начала. Это предотвращает сбой в случае, если
встречается без какого-либо предшествующего
.
Замена gsub(/^ *| *$/,"",$2)
предназначена для удаления начальных/конечных пробелов для имен категорий, которые появляются в вашем примере входного файла .xml
.
Ни один из вышеперечисленных способов не является надежным. Для правильных входных файлов xml лучше использовать реальный парсер xml, например xmlstarlet . Но для этого также потребуются правильно сформированные xml-файлы (, в примере ввода нет соответствующих тегов
, например ).