Как извлечь блок XML из файла журнала в Linux - PullRequest
1 голос
/ 14 мая 2010

У меня есть файл журнала, который выглядит следующим образом:

2010-05-12 12:23:45 Some sort of log entry
2010-05-12 01:45:12 Request XML: <RootTag>
<Element>Value</Element>
<Element>Another Value</Element>
</RootTag>
2010-05-12 01:45:32 Response XML: <ResponseRoot>
<Element>Value</Element>
</ResponseRoot>
2010-05-12 01:45:49 Another log entry

То, что я хочу сделать, это извлечь XML-код запроса и ответа (и в конечном итоге сбросить их в свои отдельные файлы). У меня был похожий парсер, который использовал egrep, но XML был в одной строке, а не в нескольких, как указано выше.

Файлы журналов также несколько большие, их размер составляет 500-600 мегабайт. Меньшие журналы, которые я читал через PHP-скрипт и использовал сопоставление регулярным выражениям, но объем памяти, необходимый для такого большого файла, скорее всего, убил бы скрипт.

Есть ли простой способ использовать встроенные инструменты на Linux-боксе (в данном случае CentOS), чтобы извлечь несколько строк, или мне придется прикусить пулю и использовать Perl или PHP, чтобы прочитать весь файл, чтобы извлечь это?

Ответы [ 3 ]

2 голосов
/ 14 мая 2010
# Example usage:
# perl script.pl data.xml RootTag > RootTag.xml

use strict;
use warnings;

my $tag = pop;

while (<>){
    if ( s/.*(<$tag>)/$1/ .. s/(<(\/)$tag>).*/$1/ ){
        print;
        last if $2;
    }
}

См. Документацию для подробностей об операторе триггер .

2 голосов
/ 14 мая 2010

Звучит как работа для sed (мне так хотелось сказать SuperSed; -)

sed -n '/^<.\+>/H; /\(Request\|Response\) XML/{s/^.*</</;x;p}; ${x;p}' xmllog

где xmllog - имя вашего файла журнала. В начале вы получите пустую строку, но ее можно отфильтровать с помощью egrep '.+' или даже tail -n +2.

В порядке пояснения, sed - это небольшой интерпретатор для программ, которые состоят из списка соответствующих условий и соответствующих действий. sed пробегает файл строка за строкой (отсюда и название «редактор потока» -> «sed») и для каждой строки для каждого условия в программе, соответствующего тексту в строке, применяет соответствующее действие. В этом случае:

/^<.\+>/

- это условие регулярного выражения, которое соответствует любой строке, содержащей <, за которой следует любой символ (.), повторенный один или несколько раз (\+), за которым следует > - практически любая строка с тегом XML. Связанное действие - H, которое добавляет строку в «буфер удержания». Другое условие

/\(Request\|Response\) XML/

, который, конечно, является регулярным выражением, которое соответствует либо Request, либо Response, за которым следует пробел, а затем XML. Соответствующее действие

{s/^.*</</;x;p}

, который сначала выполняет подстановку (s) начала строки (^), за которым следует любой символ (.), повторенный любое количество раз (*), за которым следует <, с просто <. В основном это избавляет от чего-либо до появления первого XML-тега в строке. Затем он переключает (x) только что прочитанную строку с помощью «буфера удержания» (который содержит XML предыдущего сообщения журнала) и печатает (p) материал, который был только что выгружен из буфера удержания. Наконец,

$

совпадает с концом ввода, а {x;p} снова просто заменяет содержимое буфера хранения в «буфер печати» и затем печатает его.

Вы можете изменить команду в соответствии со своими потребностями, например, если вам нужно что-то для разделения различных записей, между ними будет пустая строка:

sed -n '/^<.\+>/H; /\(Request\|Response\) XML/{s/^.*</\n</;x;p}; ${x;p}' xmllog

(в этом случае, конечно, не используйте egrep, чтобы отфильтровать пустую строку в начале).

1 голос
/ 14 мая 2010

Ваш вопрос подразумевает, что вы не думаете правильно; если есть способ сделать то, что вы просите на одном языке (есть) ... тогда вы можете сделать это на любом языке.

Нет причин читать весь журнал в память. Вы просто читаете его построчно и извлекаете нужную информацию. Вам просто нужно сохранить состояние, где вы находитесь (не в теге, внутри RootTag, внутри ResponseRoot и т. Д.) И обрабатывать данные, как вы хотите.

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