Как объединить несколько строк в одну строку, но только для блока строк, разделенных пустой строкой - PullRequest
3 голосов
/ 01 апреля 2019

Я пытаюсь объединить несколько строк в одну, но с дополнительными условиями.

Мой входной файл выглядит так:

Dm1*(  stuff1 + stuff2 -
stuff3 + stuff4)

+ D1*(D1stuff1 + D1sstuff2 + D1stuff3 + D1stuff4 +
  D1stuff5 - 
  D1stuff6 )

+ D2*(D2stuff)

Таким образом, есть несколько строк, которые также разделяются пробеломлиний.Все *stuff* содержат длинные и сложные выражения, которые также могут содержать круглые скобки.

Я хочу оставить пустые строки, как есть, но объединить другие несколько строк.

Ожидаемый результат

Dm1*(  stuff1 + stuff2 - stuff3 + stuff4)

+ D1*(D1stuff1 + D1sstuff2 + D1stuff3 + D1stuff4 + D1stuff5 - D1stuff6 )

+ D2*(D2stuff)

Все текущие попытки типа

awk '{printf("%s",$0)}' 

помещают все в одну строку.Должен ли я зацикливаться на строках или есть ли способ идентифицировать блоки между пустыми строками и применить что-то к этому?

Ответы [ 6 ]

4 голосов
/ 01 апреля 2019

Даже немного короче, чем версия John1024

awk 'BEGIN { RS=""; ORS="\n\n"}{$1=$1}1'

или

awk -v RS="" -v ORS="\n\n" '{$1=$1}1'

Использование RS="" говорит awk использовать любой абзац в качестве записи (то есть блок текста, разделенный пустыми строками). Но он также сообщает awk, что всегда является разделителем поля в сочетании с FS. Просто переопределив разделитель выходной записи ORS, мы можем вывести все, что вы захотите, сказав awk переопределить свою запись $0, сбросив первую запись $1=$1. Это приводит к тому, что все разделители полей, определенные FS (здесь используется значение по умолчанию) и символы новой строки (из-за RS=""), заменяются на OFS (по умолчанию a <пробел;>). Наконец мы печатаем запись с 1

Вы можете избавиться от всех пробелов, если дополнительно установить OFS=""

RS Первый символ строкового значения RS должен быть разделителем входных записей; по умолчанию. Если RS содержит более одного символа, результаты не указываются. Если RS равно null, то записи разделяются последовательностями, состоящими из плюс одна или несколько пустых строк, начальные или конечные пустые строки не должны приводить к пустым записям в начале или конце ввода, и всегда должен быть разделителем полей, независимо от значения FS.

источник: стандарт POSIX awk

4 голосов
/ 01 апреля 2019
awk '{if(NF!=0){printf $0}else{printf "\n\n"}}'
2 голосов
/ 01 апреля 2019

Помимо очень приятной команды awk, введенной John1024 , вы также можете использовать подход sed для вашей проблемы.

Введите:

$ cat input_file 
Dm1*(  stuff1 + stuff2 -
stuff3 + stuff4)

+ D1*(D1stuff1 + D1sstuff2 + D1stuff3 + D1stuff4 +
  D1stuff5 -
  D1stuff6 )

+ D2*(D2stuff)

Команда:

sed -n '/^$/!{H};/^$/{x;s/\n//g;s/$/\n/;p;};${x;s/\n//g;p}' input_file

Выход:

Dm1*(  stuff1 + stuff2 -stuff3 + stuff4)

+ D1*(D1stuff1 + D1sstuff2 + D1stuff3 + D1stuff4 +  D1stuff5 -  D1stuff6 )

+ D2*(D2stuff)

Пояснения:

  • -n деактивировать sed автоматическая печать
  • /^$/!{H}; Когда sed встречается с непустой строкой /^$/! добавьте эту строку в область удержания с помощью H
  • /^$/{x;s/\n//g;s/$/\n/;p;} когда sed встретится с пустой строкой /^$/, поменяйте пространство удержания и пространство шаблона x, удалите все \n в строке, которая была построена s/\n//g, добавьте \n в конце строки s/$/\n/ выведите ее p.
  • ${x;s/\n//g;p} когда sed достигает последней строки, выполните обмен пробелами / образцами x, затем удалите все \n через s/\n//g перед печатью p.
2 голосов
/ 01 апреля 2019

Попробуйте:

$ awk -v RS=  '{gsub(/ *\n */, " "); print $0 ORS}' file
Dm1*(  stuff1 + stuff2 - stuff3 + stuff4)

+ D1*(D1stuff1 + D1sstuff2 + D1stuff3 + D1stuff4 + D1stuff5 - D1stuff6 )

+ D2*(D2stuff)

Как это работает:

  • -v RS=

    Это говорит awk использовать пустые строки в качестве разделителей записей.

  • gsub(/ *\n */, " ")

    Это говорит awk о замене любых новых строк в записи вместе со всеми окружающими пробелами одним пробелом.

  • print $0 ORS

    Это говорит awk о печати записи, за которой следует разделитель выходных записей, ORS, который по умолчанию является новой строкой.

1 голос
/ 01 апреля 2019

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

sed ':a;N;/\n$/!s/\n//;ta' file

Собирать строки в пространстве шаблона, удаляя новые строки, до пустой строки.

1 голос
/ 01 апреля 2019

Использование режима абзаца Perl

perl -00 -ne ' s/\n//g; print "$_\n\n" ' file

с вашими входами

$ cat bogey.txt
Dm1*(  stuff1 + stuff2 -
stuff3 + stuff4)

+ D1*(D1stuff1 + D1sstuff2 + D1stuff3 + D1stuff4 +
  D1stuff5 -
  D1stuff6 )

+ D2*(D2stuff)
$ perl -00 -ne ' s/\n//g; print "$_\n\n" ' bogey.txt
Dm1*(  stuff1 + stuff2 -stuff3 + stuff4)

+ D1*(D1stuff1 + D1sstuff2 + D1stuff3 + D1stuff4 +  D1stuff5 -   D1stuff6 )

+ D2*(D2stuff)

$
...