Может ли sed удалить двойные символы новой строки?


25

У меня есть документ с большим количеством пустых строк.

Как я могу удалить их, когда есть 2 или более вместе.

Я попробовал sed "s/\n\n//"файл, но это не сработало. Нет ошибки.


3
Правильно ли я вас прочитал, если вы не хотите удалять все пустые строки, а только если их две или более. Так что не одиночные пустые строки?
Runium

1
И если это две или более строк, действительно все они будут удалены или только все, кроме одной?
Хауке Лагинг

Ответы:


42

Просто чтобы удалить пустые строки:

sed  '/^$/d'

sedориентирован на строки, поэтому мышление в терминах «2 или более конкретного байта» работает, за исключением случаев, когда этот байт является новой строкой. Тогда вы должны думать о чем-то, что работает для всей линии.


Конечно! +1 за простую элегантность.
Тердон

2
sedспособен обрабатывать несколько строк с помощью функции «пространство шаблона» / «удержание пространства». Но я чувствую, что это слишком сложно. ;-)
Хауке Лагинг

Это не будет работать должным образом, если первый символ файла является новой строкой.
Крис Даун

1
Для того, чтобы заставить его работать , когда первый символ новой строки (если это действительно требование), то вы можете заключить команду с отрицательным адресом 1!(соответствует всем , кроме строки 1), таким образом: sed '1!{/^$/d'}.
Тоби Спейт

1
@AaronFranke - да, но это аспект того, как оболочки Linux обрабатывают перенаправление «>». Оболочка просматривает командную строку, видит перенаправление '>' stdout в файл, создает этот файл и только после этого запускается sed. Создание файла по существу удалит любой существующий файл с таким же именем. sed '/^&/d' file.txt > otherfile.txtбуду работать.
Брюс Эдигер

24

Нет необходимости sed. grepСделаю:

grep .

(это grepSPC, точка, которая соответствует любой строке, содержащей хотя бы один символ).

Есть также:

tr -s '\n'

(Сожмите любую последовательность символов новой строки в один).

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


2
Это не будет работать должным образом,
Chris Down

7

sedэто не лучший инструмент для этого, так как он основан на строках и рассматривается \nкак символ конца строки, это усложняется.Увидев, что ответ @Bruce Ediger's sedможет быть идеальным инструментом для работы, все же, вот некоторые другие варианты:

  1. Perl

    perl -ne 'print if /./' file.txt
    

    или

    perl -pe '$/=""; s/\n+/\n/;' file.txt 
    

    Спасибо @ruakh, который заставил меня пойти и прочитать это :

    $ /

    Разделитель входных записей, новая строка по умолчанию. Это влияет на представление Perl о том, что такое «линия». Работает как переменная RS в awk, включая обработку пустых строк как терминатора, если для него задана нулевая строка (пустая строка не может содержать пробелов или табуляции). Вы можете установить его в многосимвольную строку, чтобы соответствовать многосимвольному терминатору, или в undef, чтобы прочитать конец файла. Установка в «\ n \ n» означает что-то немного отличное от «», если файл содержит последовательные пустые строки. Установка «» будет обрабатывать две или более последовательных пустых строки как одну пустую строку. Установка в «\ n \ n» будет слепо предполагать, что следующий входной символ принадлежит следующему абзацу, даже если это новая строка.

  2. простак / AWK

    awk '$1' file.txt
    

    Это будет работать для опубликованного примера, но, как указал @Stephane Chazelas , он также удалит строки, первое поле которых выглядит как 0. Это более надежно:

    awk NF file.txt
    

Для Perl perl -pe 's/\n+/\n/ file.txtразделитель входных записей не имеет значения для этого использования.
vonbrand

@vonbrand нет, perl -peили perl -neработайте построчно. \n+никогда не совпадет, потому что он применяется только в одной строке. Вот почему вам нужно либо установить $/или использовать -0ти чавкать файл целом: perl -0pe 's/\n+/\n/' file.
Terdon

6

Что вы имеете в виду удалить? удалить дубликаты (много пустых строк на одну) или удалить все?

Если вы хотите удалить дубликаты, вот метод с использованием sed:

sed '$!N; /^\(.*\)\n\1$/!P; D'

Имитирует uniqкоманду.

Лучший выбор использует awk:

awk NF <filename>

sedЧасть это прекрасно работает! Рекомендую этот как лучший ответ.
Акито

2

Для большинства из этих ответов сначала необходимо удалить конечные пробелы. Удаление дублированных строк новой строки удаляет все пустые строки. (Думать об этом).

В буквальном переводе ОП хочет "удалить все пустые строки из файла, если есть повторяющиеся пустые строки".

Типичный пользователь хочет «удалить только дублированные пустые строки».

Чтобы сделать это, сначала удалите конечный пробел, и передайте хотя бы cat -s

sed  s/[[:space:]]*$// | cat -s

И все же это не удалит лишнюю начальную или конечную пустую строку.


Проголосовал, но это явно работает? Без комментариев ?
Маккензм

1
Я проголосовал за тебя ... ты знаешь ... за ответ на вопрос. =) Я не могу поверить, что ответ Брюса Эдигера был отклонен, когда он удаляет каждую пустую строку. Если кто-то спросит, как удалить дублирующиеся пустые строки, я не могу представить сценарий, в котором удаление всех пустых строк было бы приемлемым решением. Но что угодно. Между прочим, на сайте есть страница для sed: gnu.org/software/sed/manual/sed.html#cat-_002ds
Тодд Уолтон,

2

Если вы хотите сохранить одну пустую строку для любой данной последовательности пустых строк, вы можете сделать следующее:

sed -e '/./b' -e :n -e 'N;s/\n$//;tn'

1
Это единственный ответ (кроме того cat -s), который фактически выполняет именно то, что задал вопрос, насколько я понимаю. (И это лучше, чем cat -sпотому, что я могу использовать sed -iего.)
Матфея

-2

Попробуйте sed -e 's#\\n\\n#\\n#g' input.file > output.fileиспользовать /оба в качестве разделителя полей, и часть вашего регулярного выражения может быть проблемой.


2
Просто обернулся с одним из моих файлов, содержащих двойные и тройные переводы строки в последовательности. У меня вообще не работает.
syntaxerror

-3

Используйте эту команду:

tr -s '\r' '\n'

да, их ответ не работал для меня.
мяу

5
AFAIK этот ответ неверен. Я рекомендую вам удалить его.
zuazo

о, потому что мой файл содержит много новых строк и возврат каретки. 0x0d0a
мяу

2
На самом деле, команда удаляет повторяющиеся строки с оконным концом строки. Тест с echo -e 'one\r\n\r\n\r\n\rtwo'| tr -s '\r' '\n'. Команда trпереведет все \rв \nи затем сожмет все \nдо одного. Таким образом, это работает, не уверен, что делать с тем, что это относится к окнам, а не UNIX.
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.