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

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

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

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

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

Ответ 1

Используйте это решение с GNU sed:

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

Это прочитает весь файл в цикле, а затем заменит символы новой строки пробелом.

Объяснение:

  1. Создать ярлык через :a.
  2. Добавьте текущую и следующую строку в пространство шаблона через N
  3. Если мы находимся перед последней строкой, переходите к созданной метке $!ba ($! Означает не делать это в последней строке, так как должен быть один последний символ новой строки).
  4. Наконец, подстановка заменяет каждую новую строку пробелом в пространстве образца (который является целым файлом).

Вот кросс-платформенный совместимый синтаксис, который работает с BSD и OS X sed (согласно комментарию @Benjie):

sed -e ':a' -e 'N' -e '$!ba' -e 's/\n/ /g' file

Как видите, использование sed для решения этой простой проблемы проблематично. Для более простого и адекватного решения см. Этот ответ.

Ответ 2

sed предназначен для использования на линейном вводе. Хотя он может делать то, что вам нужно.


Лучшим вариантом здесь является использование команды tr следующим образом:

tr '\n' ' ' < input_filename

или полностью удалите символы новой строки:

tr -d '\n' < input.txt > output.txt

или если у вас есть версия GNU (с ее длинными опциями)

tr --delete '\n' < input.txt > output.txt

Ответ 3

Быстрый ответ:

sed ':a;N;$!ba;s/\n/ /g' file
  • : a создать ярлык 'a'
  • N добавьте следующую строку в пространство шаблонов
  • $!, если не последняя строка, ba ветвь (перейдите на) label 'a'
  • s, /\n/ регулярное выражение для новой строки, // пробелом, /g глобальное соответствие (столько раз, сколько может)

sed будет проходить через шаг 1 до 3, пока не достигнет последней строки, получив все строки в пространстве шаблонов, где sed заменит все \n символы


Альтернативы

Все альтернативы, в отличие от sed, не нуждаются в достижении последней строки, чтобы начать процесс

с bash, медленным

while read line; do printf "%s" "$line "; done < file

с perl, sed-like speed

perl -p -e 's/\n/ /' file

с tr, быстрее, чем sed, может заменить только один символ

tr '\n' ' ' < file

с вставкой, tr-like speed, может заменяться только на один символ

paste -s -d ' ' file

с awk, tr-like speed

awk 1 ORS=' ' file

Другая альтернатива, например "echo $(< file)", работает медленно, работает только с небольшими файлами и требует обработки всего файла, чтобы начать процесс.


Длинный ответ из sed FAQ 5.10:

5,10. Почему я не могу сопоставить или удалить новую строку с помощью \n escape     последовательность? Почему я не могу сопоставить 2 или более строк с помощью \n?

\n никогда не будет соответствовать новой строке в конце строки, потому что  newline всегда удаляется до того, как линия будет помещена в  пространство рисунка. Чтобы получить 2 или более строк в пространстве шаблонов, используйте  команда "N" или что-то подобное (например, "H;...; g;" ).

Sed работает так: sed читает по одной строке за раз, отбивает  завершение новой строки, помещает то, что осталось в пространстве шаблонов, где  sed script может адресовать или изменить его, а когда пространство рисунка
 , добавляет новую строку в stdout (или в файл). Если  пространство шаблонов полностью или частично удаляется с помощью "d" или "D",  Новая строка не добавляется в таких случаях. Таким образом, скрипты типа

  sed 's/\n//' file       # to delete newlines from each line             
  sed 's/\n/foo\n/' file  # to add a word to the end of each line         

НИКОГДА не будет работать, потому что конечная новая строка будет удалена до того, как  строка помещается в пространство рисунка. Выполнение вышеуказанных задач,
 вместо этого используйте один из этих сценариев:

  tr -d '\n' < file              # use tr to delete newlines              
  sed ':a;N;$!ba;s/\n//g' file   # GNU sed to delete newlines             
  sed 's/$/ foo/' file           # add "foo" to end of each line          

Так как версии sed, отличные от GNU sed, имеют ограничения по размеру  буфер шаблонов, утилита Unix 'tr' здесь предпочтительнее.
 Если последняя строка файла содержит новую строку, GNU sed добавит  что новая строка выводится, но удаляет все остальные, тогда как tr будет  удалить все новые строки.

Чтобы соответствовать блоку из двух или более строк, существует 3 основных варианта:
 (1) используйте команду "N" , чтобы добавить следующую строку в пространство шаблона,
 (2) используйте команду "H", по крайней мере, дважды, чтобы добавить текущую строку
 в пространство удержания, а затем извлеките линии из удержания пространства
 с x, g или G; или (3) использовать диапазоны адресов (см. раздел 3.3 выше)
 для соответствия строк между двумя указанными адресами.

Варианты (1) и (2) помещают \n в пространство шаблонов, где он  могут быть адресованы по желанию ('s/ABC\nXYZ/alphabet/g'). Один пример
 использования "N" для удаления блока строк в разделе 4.13
 ( "Как удалить блок определенных строк подряд?" ). Это
 пример можно изменить, изменив команду delete на что-то  else, например 'p' (print), 'i' (insert), 'c' (change), 'a' (добавить),
 или 's' (заменить).

Выбор (3) не помещает \n в пространство шаблонов, но он делает  сопоставьте блок последовательных строк, так что может быть, что вы не используете  даже нужно \n найти то, что вы ищете. Поскольку GNU sed  версия 3.02.80 теперь поддерживает этот синтаксис:

  sed '/start/,+4d'  # to delete "start" plus the next 4 lines,           

в дополнение к традиционному '/отсюда/,/до там /{...}' range  адресов, можно избежать использования \n полностью.

Ответ 4

Более короткая альтернатива awk:

awk 1 ORS=' '

объяснение

Программа awk состоит из правил, которые состоят из условных кодовых блоков, а именно:

condition { code-block }

Если кодовый блок опущен, используется значение по умолчанию: { print $0 }. Таким образом, 1 интерпретируется как истинное условие, и print $0 выполняется для каждой строки.

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

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

Ответ 5

gnu sed имеет опцию -z для нулевых разделенных записей (строк). Вы можете просто позвонить:

sed -z 's/\n/ /g'

Ответ 6

Версия Perl работает так, как вы ожидали.

perl -i -p -e 's/\n//' file

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

Ответ 7

Кому нужно sed? Вот путь bash:

cat test.txt |  while read line; do echo -n "$line "; done

Ответ 8

Чтобы заменить все символы новой строки пробелами с помощью awk, не читая весь файл в памяти:

awk '{printf "%s ", $0}' inputfile

Если вы хотите окончательную новую строку:

awk '{printf "%s ", $0} END {printf "\n"}' inputfile

Вы можете использовать символ, отличный от пробела:

awk '{printf "%s|", $0} END {printf "\n"}' inputfile

Ответ 9

Три вещи.

  • tr (или cat и т.д.) абсолютно не требуется. (GNU) sed и (GNU) awk, при объединении, может сделать 99,9% любой текстовой обработки, в которой вы нуждаетесь.

  • поток!= строка. ed - это линейный редактор. sed нет. Подробнее о различии см. sed lecture. Большинство людей путают sed как линейную, потому что по умолчанию она не очень жадна в сопоставлении шаблонов для совпадений SIMPLE - например, при выполнении поиска шаблона и замены на один или два символа он по умолчанию заменяет только первое совпадение, которое он находит (если не указано иначе глобальной командой). Не было бы глобальной команды, если бы она была построена на основе строки, а не на основе STREAM, потому что она оценивала бы только строки за раз. Попробуйте запустить ed; вы заметите разницу. ed очень полезен, если вы хотите перебирать определенные строки (например, для цикла), но в большинстве случаев вам просто нужно sed.

  • При этом

    sed -e '{:q;N;s/\n/ /g;t q}' file
    

    отлично работает в GNU sed версии 4.2.1. Вышеупомянутая команда заменит все новые строки пробелами. Это уродливое и немного громоздкое, но оно работает отлично. {} можно оставить без внимания, поскольку они включены только по соображениям здравомыслия.

Ответ 10

tr '\n' ' ' 

- это команда.

Простой и удобный.

Ответ 11

Ответ с меткой: <... >

Как заменить новую строку (\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 script в файл или используйте -e для "сборки" sed script...

> (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 похож.

Ответ 12

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

У меня была эта проблема. Главное, что мне нужно решение для работы с 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 чтобы поменять местами дополнительные символы новой строки, если они вам нужны

Ответ 13

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

seq 10 | xargs

или

seq 10 | xargs echo -n

Ответ 14

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

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

От man sed:

[2addr] N

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

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

Ответ 15

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

tr '\n' ' ' < input

не работал у меня, это либо ошибка, либо, по крайней мере, заменит \n w/''.

Используя другую функцию tr, опция "удалить" -d действительно работает:

tr -d '\n' < input

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

Ответ 16

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

echo -e "a\nb\nc\n" |tr '\n' '\t' | sed 's/\t/ <br> /g'`

Ответ 17

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

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

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

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

Я обрабатываю MB и даже GB данных, и единственным ограничением, которое я нашел, является размер строки.

Ответ 18

Пуленепробиваемое решение. Бинарные данные безопасны и 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: sh, язык команд оболочки, od, tr, grep, read, [, printf.

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

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

Ответ 19

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

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

Ответ 20

Находит и заменяет, используя \n

sed -ie -z 's/Marker\n/# Marker Comment\nMarker\n/g' myfile.txt

маркер

становится

# Комментарий маркера

маркер

Ответ 21

Если вам не повезло иметь дело с окончаниями строк Windows, вам нужно удалить \r и \n

tr '[\r\n]' ' ' < $input > $output

Ответ 22

В Mac OS X (с использованием команды FreeBSD):

# replace each newline with a space
printf "a\nb\nc\nd\ne\nf" | sed -E -e :a -e '$!N; s/\n/ /g; ta'
printf "a\nb\nc\nd\ne\nf" | sed -E -e :a -e '$!N; s/\n/ /g' -e ta

Ответ 23

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

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

Ответ 24

Использование Awk:

awk "BEGIN { o=\"\" }  { o=o \" \" \$0 }  END { print o; }"

Ответ 25

В частности, я хотел бы добавить весь файл в пространство удержания и заменить все строки новой строки в конце файла:

$ (echo foo; echo bar) | sed -n 'H;${x;s/\n//g;p;}'
foobar

Однако кто-то сказал мне, что пространство удержания может быть конечным в некоторых реализациях sed.

Ответ 26

Замените строки новой строки любой строкой и замените последнюю строку новой строки

Чистые решения tr могут заменяться только одним символом, а чистые решения sed не заменяют последнюю новую строку ввода. Следующее решение устраняет эти проблемы и, по-видимому, безопасно для двоичных данных (даже с локалью UTF-8):

printf '1\n2\n3\n' |
  sed 's/%/%p/g;s/@/%a/g' | tr '\n' @ | sed 's/@/<br>/g;s/%a/@/g;s/%p/%/g'

Результат:

1<br>2<br>3<br>

Ответ 27

Это sed, который вводит новые строки после "нормальной" замены. Во-первых, он обрезает новую строку char, затем обрабатывается в соответствии с вашими инструкциями, затем вводит новую строку.

Используя sed, вы можете заменить "конец" строки (а не на новую строку char) после обрезки с указанием строки по вашему выбору для каждой строки ввода; но sed выводит разные строки. Например, предположим, что вы хотите заменить "конец строки" на "===" (более общий, чем замена одним пространством):

PROMPT~$ cat <<EOF |sed 's/$/===/g'
first line
second line
3rd line
EOF

first line===
second line===
3rd line===
PROMPT~$

Чтобы заменить новую строку char на строку, вы можете, неэффективно, использовать tr, как указано выше, чтобы заменить символы новой строки "специальным char" а затем используйте sed, чтобы заменить этот специальный char на нужную строку.

Например:

PROMPT~$ cat <<EOF | tr '\n' $'\x01'|sed -e 's/\x01/===/g'
first line
second line
3rd line
EOF

first line===second line===3rd line===PROMPT~$

Ответ 28

Другой метод GNU sed, почти такой же, как ответ Zsolt Botykai, но в нем используется команда sed редко используемая y (транслитерация), которая сохраняет один байт кода (конечный g):

sed ':a;N;$!ba;y/\n/ /'

Можно было бы надеяться, что y будет работать быстрее s (возможно, на скорости tr, в 20 раз быстрее), но в GNU sed v4.2.2 y примерно на 4% медленнее, чем s.


Более портативная версия BSD sed:

sed -e ':a' -e 'N;$!ba' -e 'y/\n/ /'

Ответ 29

@OP, если вы хотите заменить новые строки в файле, вы можете просто использовать dos2unix (или unix2dox)

dos2unix yourfile yourfile

Ответ 30

Вы также можете использовать этот метод

sed 'x;G;1!h;s/\n/ /g;$!d'

Объяснение

x   - which is used to exchange the data from both space (pattern and hold).
G   - which is used to append the data from hold space to pattern space.
h   - which is used to copy the pattern space to hold space.
1!h - During first line won't copy pattern space to hold space due to \n is
      available in pattern space.
$!d - Clear the pattern space every time before getting next line until the
      last line.

Поток:
 Когда первая строка поступает с входа, происходит обмен, поэтому 1 переходит в удержание пространства, а \n - в пространство шаблонов, затем добавляет пространство удержания в пространство шаблонов, а затем выполняется замещение и удаление пространства шаблонов.
 Во время второй линии выполняется обмен, 2 переходит в удержание пространства, а 1 - в пространство рисунка, затем G добавляет пространство удержания в пространство шаблонов, затем h копирует шаблон в него, а подстановка делается и удаляется. Эта операция продолжается до тех пор, пока не будет достигнута точность, а затем напечатайте точный результат.