Команда Awk в режиме абзаца, но пропускаются пустые строки

У меня один файл с несколькими элементами <elem>...</elem>, Мне нужно разделить этот файл на n файлы с m каждый элемент (аргумент передается команде awk, которую я использую). Например, если мой исходный файл содержит 40 элементов, я бы хотел разделить его на 3 файла (10 элементов, 13 элементов и 17 элементов).

Проблема в том, что исходный файл имеет элементы с различными структурами.

EDITED AFTER fedorqui comment:
I use as awk command as files I want to get at the end of the process. 
That means If I need 3 files with m1, m2 and m3 elements, I will 
execute 3 awk with different parameters

Пример ввода (file.txt) (5 элементов)

<elem>aaaaaaaa1</elem>
<elem>aaaaaaaa2</elem>
<elem>bbbbbbbb
bbbbbbbbb
bbbbbbbbb</elem>
<elem>bbbbbbbb2</elem>
<elem>ccccc

cccc</elem>

Как видите, 1/2/4-й элемент находится в одной строке, 3-й элемент - в 3 строки без пустых строк, а 5-й элемент - в 3 строки с пустой строкой.

Пустые строки между элементами не проблема, но пустые строки внутри элемента терпят неудачу

Пример желаемого результата:

file_1.txt (2 элемента)

<elem>aaaaaaaa1</elem>
<elem>aaaaaaaa2</elem>

file_2.txt (2 элемента)

<elem>bbbbbbbb
bbbbbbbbb
bbbbbbbbb</elem>
<elem>bbbbbbbb2</elem>

file_3.txt (1 элемент)

<elem>ccccc

cccc</elem>

Команда AWK

(Суффикс File - это номер суффикса файла. Например, fileAux_1.txt, fileAux_2.txt...)

Attempt1

awk -v numElems=$1 -v suffixFile=$2 '{
    for(i=1;i<=numElems;i++) {
        printf "<doc>"$i > "fileAux_" suffixFile".txt"
    }
}' RS='' FS='<doc>' file.txt

Работает за исключением пустых строк внутри элемента. Я понимаю, почему это не удается, потому что RS='' говорит awk разделить на пустые строки

Попытка 2

awk -v numElems=$1 -v suffixFile=$2 '{
    for(i=1;i<=numElems;i++) {
        printf $i > "fileAux_" suffixFile".txt"
    }
}' RS='<doc>' FS='<doc>' file.txt

Еще один подход, но он также терпит неудачу

Может кто-нибудь мне помочь?

Заранее спасибо!

1 ответ

Если я правильно понял ваш вызов, вот моя попытка:

$ cat script.sh 
#!/bin/bash

awk -v numElems=$1 -v suffixFile=$2 '
        /<elem>/{var++}
        /<\/elem>/{var--; count++} 
        {if(count < numElems || (count == numElems && var == 0)) {
                print $0 >> "file_"suffixFile".txt"
        } else {
                print $0
        } }' $3

Сценарий в основном отслеживает <elem> а также </elem> замыкания с var и считает пары с count, Тогда оператор if решает, вставить ли строку в файл или нет. Как только общее количество элементов достигнуто, остальная часть файла возвращается, чтобы вы могли повторить процесс, используя каналы.

Вот пример того, как запустить его с окончательным выводом:

$ ./script.sh 2 1 file.txt | ./script.sh 2 2 | ./script.sh 1 3
$ tail -n +1 file_*
==> file_1.txt <==
<elem>aaaaaaaa1</elem>
<elem>aaaaaaaa2</elem>

==> file_2.txt <==
<elem>bbbbbbbb
bbbbbbbbb
bbbbbbbbb</elem>
<elem>bbbbbbbb2</elem>

==> file_3.txt <==
<elem>ccccc

cccc</elem>
Другие вопросы по тегам