Разделить файл на основе начального и конечного тега XML

Разделить файл на основе начального и конечного тега XML

Можно ли использовать функцию split для разделения файла на несколько сегментов, размер каждого из которых зависит от количества совпадений элемента XML?

Например, для XML-разбиения ниже, когда количество встреч "<test xsi:type="update" locale="en_US">" равно 2

<?xml version="1.0" encoding="UTF-8"?>
<testers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<test xsi:type="update" locale="en_US">
<rval>1</rval>
</test>
<test xsi:type="update" locale="en_US">
<rval>1</rval>
</test>
<test xsi:type="update" locale="en_US">
<rval>1</rval>
</test>
</testers>

Разделение указанного выше XML-файла должно привести к созданию 2 файлов.

файл1 :

<test xsi:type="update" locale="en_US">
<rval>1</rval>
</test>
<test xsi:type="update" locale="en_US">
<rval>1</rval>
</test>

и файл 2, содержащий только одну запись:

<test xsi:type="update" locale="en_US">
<rval>1</rval>
</test>

Вот что я пытаюсь сделать:

split -p "<test xsi:type=\"update\" locale=\"en_US\">" test.xml segment

который выводит 4 файла:

сегментаа :

<?xml version="1.0" encoding="UTF-8"?>
<testers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">

сегментаб :

<test xsi:type="update" locale="en_US">
<rval>1</rval>
</test>

сегментак :

<test xsi:type="update" locale="en_US">
<rval>1</rval>
</test>

сегментад:

<test xsi:type="update" locale="en_US">
<rval>1</rval>
</test>
</testers>

Можно splitиспользовать так, как я предлагаю. Файл, который я обрабатываю, имеет размер 40 ГБ, я использую приведенный выше пример, чтобы проиллюстрировать проблему, которую пытаюсь решить.

решение1

Я не думаю, что это возможно с split. Вы могли бы использовать awk:

awk '
  BEGIN{ 
    fmt="segment%02d"               # 2 digits for suffix, zero padded
    start="<test xsi:type=\"update\" locale=\"en_US\">"
    end="</test>"
  }
  $0 == start, $0 == end{
    if ($0 == start && ++cnt%2==1){ # for every 2nd start element...
      fname=sprintf(fmt, fcnt++)    # update output filename
    }
    print $0 > fname                # print line, redirect output to fname
  }
' test.xml

Это создает два файла segment00и segment01:

$ head segment*
==> segment00 <==
<test xsi:type="update" locale="en_US">
<rval>1</rval>
</test>
<test xsi:type="update" locale="en_US">
<rval>1</rval>
</test>

==> segment01 <==
<test xsi:type="update" locale="en_US">
<rval>1</rval>
</test>

Связанный контент