Заменить повторяющиеся пустые строки на одну пустую строку


ramok аватар

ramok - Posted on 13 Август 2007

Допустим у вас есть файл в котором множество повторяющихся пустых строк. А вам
хотелось бы повторяющиеся пустые строки заменить на одну пустую строку (что бы
было легче читать например).

sed -e ':a;/^$/N;/\n$/{D;ba}' file.txt

Примечание:


В *BSD системах, однострочник придется оформить так:

sed -e :a -e '/^$/N;/\n$/{D;ba' -e '}' file.txt

так как после имени метки и перед } необходим перевод строки.

Объяснение как это работает

этот однострочник - аналог скрипт файла

#/usr/bin/env sed -f
:a        # метка с именем a
/^$/N     # если найдена пустая строка (/^$/),
          # то к текущей строке добавить следующую(Next)
/\n$/ {   # если следующя строка пустая  (/\n$/)
    D     # то удалить предыдущую строку (Delete)(тоже пустую)
    b a   # goto  a; то есть перейти на метку :a
}

Дополнение


Еще доступный вариант который будет работать везде:

sed -e :a -e '/^$/N;/\n$/!b;D;ba' file.txt

Объяснение как это работает 2

#/usr/bin/env sed -f
:a        # метка с именем a
/^$/N     # если найдена пустая строка (/^$/),
          # то к текущей строке добавить следующую
/\n$/!b   # если следующая строка НЕ (!пустая  (/\n$/),
          # то закончить обработку текущей строки b(то есть выведется
          # и перевод строки и текущая строка строка.
D         # если предыдущая строка была пустой, то удалить первую пустую строку
          # D
ba        # goto a; то есть перейти на метку :a

то есть это по аналогу с псевдокодом первый вариант работает по принципу

 if (пустая строка)
 {
    удалить строку предыдущую строку;
    goto a;
 }

а второй:

 if (не пустая строка)
 {
    goto к обработке следующей строчке;
 }
 else
 {
    удалить строку предыдущую строку;
    goto a;
 }
0
Ваша оценка: Ничего

cat -s :)

cut -s

доступный вариант который будет работать везде :))

cut -s не пропустит вообще пустые строки, а задача в другом
--
Signature invent in progress 24% ##........

в vim это можно сделать командой:
:%s!^\_s*$!!

как побочный эффект - удалит хвосты пробелов в пустых строках

удивительно. разобрался как это работает, не припомню таких регеспов где бы то нибыло.
\_s мачит все пробелы включая перевод строки. В сочетании с ^\_s*$ дает нужный эффект, так как $ тут обозначает уже не конец текущей строки, а конец любой последующей строки которая подходит под регесп.

sed работает с каждой строкой отдельно, и такого эффекта тоже можно добится, но предварительно нужно считать в буфер следующую строчку не потеряв предыдущей.

супер спасибо Ж:-)
повод изучить регеспы vim-ма подробней

PS
обработать файл в пакетном режиме в vim можно так
vim -c '%s/^\_s*$// | wq' file.txt
--
Signature invent in progress 24% ##........

Как сказал тут уже кто-то "что только народ не придумает, чтобы маны не читать" :)

Цитирую из man tr

Цитата:
-s, --squeeze-repeats
replace each input sequence of a repeated character that is
listed in SET1 with a single occurrence of that character

ну и

Цитата:
\n new line

\r return

Хотя, если честно, сам об этой опции только недавно узнал ;)

век живи, век rtfm Ж:-) снкс
PS
хотя первое предложение контрастирует с последним. для того и этот сайт, что бы делится тем из манов, чего другие могли не увидеть Ж:-)
--
Signature invent in progress 24% ##........

По-моему, гораздо проще удалять повторяющиеся строки командой uniq

uniq удалит все повторяющиеся строки
а хочется только пустые
--
Signature invent in progress 24% ##........