Как я могу объединить каждый блок из 3 строк вместе, игнорируя при этом меньшее количество последовательных строк? - PullRequest
1 голос
/ 03 апреля 2020

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

AAAAAAAAAAAAA
BBBBBBBBBBBBB
CCCCCCCCCCCCC
DDDDDDDDDDDDD
EEEEEEEEEEEEE
FFFFFFFFFFFFF

GGGGGGGGGGGGG

HHHHHHHHHHHHH
IIIIIIIIIIIII
JJJJJJJJJJJJJ

KKKKKKKKKKKKK

LLLLLLLLLLLLL
MMMMMMMMMMMMM
NNNNNNNNNNNNN
OOOOOOOOOOOOO
PPPPPPPPPPPPP
QQQQQQQQQQQQQ
RRRRRRRRRRRRR
SSSSSSSSSSSSS
TTTTTTTTTTTTT

UUUUUUUUUUUUU

VVVVVVVVVVVVV
WWWWWWWWWWWWW
XXXXXXXXXXXXX
YYYYYYYYYYYYY
ZZZZZZZZZZZZZ
1111111111111

Я хотел бы объединить каждый блок из 3 последовательных строк начиная с первого в блоке. Я хочу игнорировать строки, которые находятся менее чем в блоке из 3 последовательных строк. Символы и длины строк всегда разные. (я сделал линии одинакового размера в примере, чтобы он не выглядел слишком уродливо).

Таким образом, результат будет

AAAAAAAAAAAAA BBBBBBBBBBBBB CCCCCCCCCCCCC
DDDDDDDDDDDDD EEEEEEEEEEEEE FFFFFFFFFFFFF

GGGGGGGGGGGGG

HHHHHHHHHHHHH IIIIIIIIIIIII JJJJJJJJJJJJJ

KKKKKKKKKKKKK

LLLLLLLLLLLLL MMMMMMMMMMMMM NNNNNNNNNNNNN
OOOOOOOOOOOOO PPPPPPPPPPPPP QQQQQQQQQQQQQ
RRRRRRRRRRRRR SSSSSSSSSSSSS TTTTTTTTTTTTT

UUUUUUUUUUUUU

VVVVVVVVVVVVV WWWWWWWWWWWWW XXXXXXXXXXXXX
YYYYYYYYYYYYY ZZZZZZZZZZZZZ 1111111111111

Я пытался использовать

xargs -n3

Однако я не уверен, как игнорировать особые строки

Как я могу добиться этого?

Ответы [ 4 ]

3 голосов
/ 03 апреля 2020

С GNU awk для gensub():

$ awk -v RS= -v ORS='\n\n' '{$1=$1; print gensub(/(([^ ]+ ){2}[^ ]+) /,"\\1\n","g")}' file
AAAAAAAAAAAAA BBBBBBBBBBBBB CCCCCCCCCCCCC
DDDDDDDDDDDDD EEEEEEEEEEEEE FFFFFFFFFFFFF

GGGGGGGGGGGGG

HHHHHHHHHHHHH IIIIIIIIIIIII JJJJJJJJJJJJJ

KKKKKKKKKKKKK

LLLLLLLLLLLLL MMMMMMMMMMMMM NNNNNNNNNNNNN
OOOOOOOOOOOOO PPPPPPPPPPPPP QQQQQQQQQQQQQ
RRRRRRRRRRRRR SSSSSSSSSSSSS TTTTTTTTTTTTT

UUUUUUUUUUUUU

VVVVVVVVVVVVV WWWWWWWWWWWWW XXXXXXXXXXXXX
YYYYYYYYYYYYY ZZZZZZZZZZZZZ 1111111111111
2 голосов
/ 03 апреля 2020

В awk:

$ awk -v FS="\n" -v RS="" '{for(i=1;i<=NF;i+=3)print $i,$(i+1),$(i+2);print ""}' file

Вывод:

AAAAAAAAAAAAA BBBBBBBBBBBBB CCCCCCCCCCCCC
DDDDDDDDDDDDD EEEEEEEEEEEEE FFFFFFFFFFFFF

GGGGGGGGGGGGG  

HHHHHHHHHHHHH IIIIIIIIIIIII JJJJJJJJJJJJJ

...

Обновление Версия, которая не покидает конечный пробел:

$ awk -v FS="\n" -v RS="" '{for(i=1;i<=NF;i++)printf "%s%s",$i,(i%3==0||i==NF?ORS:OFS);print ""}' file

Пожалуйста, смотрите обсуждение некоторых функций в комментариях. Спасибо комментаторам за конструктивную обратную связь.

1 голос
/ 03 апреля 2020

Вот другое, которое всегда будет работать:

awk '(NF==0){print rec ORS; rec="";c=0; next}
     {rec = rec (c ? (c%3==0 ? ORS : OFS) : "") $0; c++ }
     END {print rec}' file
0 голосов
/ 03 апреля 2020

Это может работать для вас (GNU sed):

sed '/\S/{N;/\n\s*$/b;N;//b;s/\n/ /g}' file

Если текущая строка не пуста, добавьте следующую строку.

Если добавленная строка не пуста, добавьте следующая строка.

Если эта строка также не пуста, замените символы новой строки пробелами.

Во всех остальных случаях выведите строки как есть.

An альтернатива, то есть больше программирования c:

sed ':a;N;s/\n/&/2;Ta;/^\s*$/M{P;D};s/\n/ /g' file
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...