Как заменить символ новой строки (\ n) с помощью sed? - PullRequest
1233 голосов
/ 09 августа 2009

Как заменить символ новой строки (\n) командой sed?

Я безуспешно пытался:

sed 's#\n# #g' file
sed 's#^$# #g' file

Как мне это исправить?

Ответы [ 41 ]

12 голосов
/ 25 сентября 2009

Ответ с меткой ...

Как заменить символ новой строки (\ n) с помощью sed?

... не работает в freebsd 7.2 в командной строке:

( echo foo ; echo bar ) | sed ':a;N;$!ba;s/\n/ /g'
sed: 1: ":a;N;$!ba;s/\n/ /g": unused label 'a;N;$!ba;s/\n/ /g'
foo
bar

Но если вы помещаете скрипт sed в файл или используете -e для "сборки" сценария sed ...

> (echo foo; echo bar) | sed -e :a -e N -e '$!ba' -e 's/\n/ /g'
foo bar

или ...

> cat > x.sed << eof
:a
N
$!ba
s/\n/ /g
eof

> (echo foo; echo bar) | sed -f x.sed
foo bar

Возможно, sed в OS X похож.

10 голосов
/ 17 мая 2014

Вы можете использовать xargs :

seq 10 | xargs

или

seq 10 | xargs echo -n
10 голосов
/ 25 января 2012

Простое для понимания решение

У меня была эта проблема. Главное, что мне нужно было решение для работы с BSD (Mac OS X) и GNU (Linux и Cygwin ) sed и tr:

$ echo 'foo
bar
baz


foo2
bar2
baz2' \
| tr '\n' '\000' \
| sed 's:\x00\x00.*:\n:g' \
| tr '\000' '\n'

Выход:

foo
bar
baz

(завершающий перевод строки)

Работает в Linux, OS X и BSD - даже без поддержки UTF-8 или с дерьмовым терминалом.

  1. Используйте tr для замены новой строки на другой символ.

    NULL (\000 или \x00) - это хорошо, потому что ему не нужна поддержка UTF-8, и он вряд ли будет использоваться.

  2. Используйте sed, чтобы соответствовать NULL

  3. Используйте tr, чтобы заменить дополнительные символы новой строки, если они вам нужны

9 голосов
/ 10 августа 2009

Я не эксперт, но, думаю, в sed вам сначала нужно добавить следующую строку в пространство шаблона, используя bij, используя "N". Из раздела «Пространство многострочного шаблона» в «Расширенных командах sed» книги sed & awk (Дейл Догерти и Арнольд Роббинс; O'Reilly 1997; стр. 107 в превью ) :

Многострочная команда Next (N) создает многострочное пространство шаблонов, читая новую строку ввода и добавляя ее к содержимому пространства шаблонов. Исходное содержимое пространства шаблона и новая строка ввода разделены новой строкой. Встроенный символ новой строки можно сопоставить в шаблонах с помощью escape-последовательности "\ n". В многострочном шаблонном пространстве метасимвол «^» соответствует самому первому символу шаблонного пространства, а не символу (ам) после любой встроенной новой строки (ей). Точно так же «$» соответствует только последней новой строке в пространстве шаблона, а не любой встроенной новой строке (строкам). После выполнения команды Next управление передается последующим командам в сценарии.

С man sed:

[2addr] N

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

Я использовал это для поиска (нескольких) плохо отформатированных файлов журналов, в которых строка поиска может быть найдена в "потерянной" следующей строке.

6 голосов
/ 13 марта 2012

Я использовал гибридный подход для обхода новой строки, используя tr для замены новой строки на вкладки, а затем заменяя вкладки на все, что я хочу. В этом случае "
", так как я пытаюсь сгенерировать разрывы HTML.

echo -e "a\nb\nc\n" |tr '\n' '\t' | sed 's/\t/ <br> /g'`
6 голосов
/ 26 февраля 2011

В ответ на приведенное выше решение «tr» в Windows (возможно, с использованием версии tr для Gnuwin32) предлагаемое решение:

tr '\n' ' ' < input

не работал для меня, он либо по ошибке, либо фактически заменял \ n w / '' по какой-то причине.

Используя другую функцию tr, опция -d «delete» сработала:

tr -d '\n' < input

или '\ r \ n' вместо '\ n'

5 голосов
/ 19 апреля 2014

Пуленепробиваемое решение. Безопасный для двоичных данных и POSIX-совместимый, но медленный.

POSIX sed требует ввода в соответствии с POSIX текстовый файл а также линия POSIX определения, поэтому NULL-байты и слишком длинные строки не допускаются, и каждая строка должна заканчиваться символом новой строки (включая последнюю строку). Это затрудняет использование sed для обработки произвольных входных данных.

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

od -A n -t o1 -v | tr ' \t' '\n\n' | grep . |
  while read x; do [ "0$x" -eq 012 ] && printf '<br>\n' || printf "\\$x"; done

Справочная документация POSIX: ш , командный язык оболочки , от , тр , Grep , прочитать , [, Printf .

Оба read, [ и printf являются встроенными по крайней мере в bash, но это, вероятно, не гарантируется POSIX, поэтому на некоторых платформах может случиться так, что каждый входной байт будет начинать один или несколько новые процессы, которые будут тормозить вещи. Даже в bash это решение достигает только 50 кБ / с, поэтому оно не подходит для больших файлов.

Протестировано на Ubuntu (bash, dash и busybox), FreeBSD и OpenBSD.

5 голосов
/ 19 октября 2011

В некоторых ситуациях вы можете изменить RS на другую строку или символ. Таким образом, \ n доступен для sub / gsub:

$ gawk 'BEGIN {RS="dn" } {gsub("\n"," ") ;print $0 }' file

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

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

Я обрабатываю МБ и даже ГБ данных, и единственное ограничение, которое я нашел, - это размер строки.

4 голосов
/ 28 марта 2013

Вы можете использовать xargs & mdash; по умолчанию \n будет заменен пробелом.

Однако могут возникнуть проблемы, если на вашем входе есть регистр unterminated quote, например если кавычки на данной строке не совпадают.

3 голосов
/ 06 июня 2011

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

sed -n "s/^$//;t;p;"
...