Извлечь конкретный шаблон XML из файла журнала, используя 'awk' - PullRequest
0 голосов
/ 06 октября 2018

Я хотел бы извлечь из файла журнала, который в основном содержит данные журнала Java (отладка / ошибки / информация), следующий XML:

<envelope>
    <header>
        ...
    </header>
    <body>
        <Provision>
            <ORDER id="XYZ_123_456" action="test">
                ....
            </ORDER>
        </Provision>
    </body>
</envelope>

Мне нужен только тот файл, который имеет тег «Provision»и который содержит идентификатор ORDER XYZ_123_456

Я пытался использовать следующее, но он также возвращает XML без тега Provision.(Я почти ничего не знаю в awk, это код, который я изменил для этой конкретной потребности)

awk '/<envelope>/ {line=$0; p=0 && x=0; next}
     line   {line=line ORS $0}
    /ORDER/ && $2~/XYZ_123_456/ {p=1}
    $0~/<Provision>/ {x=1}
   /<\/envelope>/ && p && x {print line;}' dump.file

Спасибо!

Ответы [ 3 ]

0 голосов
/ 07 октября 2018

Если ваш XML-файл или файл журнала настолько хорошо сформирован, как вы заявляете, вы можете (ab) использовать awk и его RS функцию разделителя записей, чтобы выполнить большую часть анализа для вас:

 awk 'BEGIN{ RS="</envelope>"; FS="<envelope>" }; $0 ~ order { print "<envelope>",$2,"</envelope>" }' order=XYZ_123_456 tmp.txt

Это работает, определяя </envelope> как разделитель записей awk, а затем читая все вещи между </envelope> строками.Чтобы затем раздеть / разделить другие сообщения журнала, я использую разделитель полей FS, чтобы разделить «строку» на столбцы, и вывести второй столбец.

Это ужасно не удастся, если произойдет <envelope> или </envelope> Строка может появиться где-нибудь еще в ваших данных журнала, но вы уже указали на лучшие парсеры XML.

Поскольку для вышеприведенного решения требуется GNU awk для multi-char RS, здесь то же самое решениеиспользуя perl для случая, когда нет подходящей версии awk:

 perl -ne 'BEGIN{ $/="</envelope>";$order=shift }; /<envelope>.*$order.*/ms and print $&' XYZ_123_456 tmp.txt
0 голосов
/ 07 октября 2018
$ cat tst.awk
/<envelope>/ { inEnv = 1 }
inEnv { env = env $0 ORS }
/<\/envelope>/ {
    if ( env ~ /<Provision>.*<ORDER[[:space:]]+id="XYZ_123_456"/ ) {
        printf "%s", env
    }
    env = inEnv = ""
}

$ awk -f tst.awk file
<envelope>
    <header>
        ...
    </header>
    <body>
        <Provision>
            <ORDER id="XYZ_123_456" action="test">
                ....
            </ORDER>
        </Provision>
    </body>
</envelope>
0 голосов
/ 07 октября 2018

Вы не должны анализировать xml с помощью awk.Лучше использовать xmlstarlet.Это напечатает весь конверт:

$ apt-get install xmlstarlet
$ xmlstarlet sel -t -c '/envelope/body/Provision/ORDER[@id="XYZ_123_456"]/../../..' file.xml

Для awk, я предлагаю это:

awk '
    !el&&/<envelope>/{el=1}
    el==1&&/<body>/{el=2}
    el==2&&/<Provision>/{el=3}
    el==3&&/<ORDER.*id="XYZ_123_456"/{el=4;hit=1}
    el>0{buffer=buffer $0 ORS}
    el==4&&/<\/ORDER>/{el=3}
    el==3&&/<\/Provision>/{el=2}
    el==2&&/<\/body>/{el=1}
    el==1&&/<\/envelope>/{el=0;if (hit){print buffer; buffer="";hit=0}}
' file.xml

Это проверяет правильную структуру XML и печатает весь конверт, если присутствуют элементы xmlразные строки каждая.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...