web-dev-qa-db-ja.com

Sedを使って改行(\ n)を入れ替えるにはどうすればいいですか?

Sedコマンドを使って改行(\n)を置き換えるにはどうすればいいですか?

私は失敗しました:

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

どうやって直すの?

1222
hhh

このソリューションをGNU sedと共に使用します。

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

これはファイル全体をループで読み込み、改行をスペースに置き換えます。

説明:

  1. :aでラベルを作成してください。
  2. 現在および次の行をNを介してパターンスペースに追加します。
  3. 最後の行の前にいる場合は、作成されたラベル$!baに分岐します($!は、最後の改行が1つあるはずなので、最後の行では行わないことを意味します)。
  4. 最後に、置換はすべての改行をパターンスペース上のスペース(ファイル全体)で置き換えます。

BSDとOS Xのsed@Benjieコメント )に従って動作する、クロスプラットフォーム互換の構文は次のとおりです。

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

見ての通り、そうでなければ簡単な問題のためにsedを使うことは問題が多いです。もっと簡単で適切な解決策は この答え を見てください。

1371
Zsolt Botykai

代わりにtrを使用しますか?

tr '\n' ' ' < input_filename

または改行文字を完全に削除します。

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

またはGNUバージョン(長いオプション付き)がある場合

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

速い答え:

sed ':a;N;$!ba;s/\n/ /g' file
  1. :aラベル「a」を作成
  2. N次の行をパターンスペースに追加する
  3. $!最後の行ではない場合babranch(go to)label 'a'
  4. ssubstitute/\n /新しい行の正規表現/ /byスペース/ gグローバルマッチ(可能な限り)

sedは最後の行に達するまでステップ1から3をループし、sedがすべての\ n文字を置換するパターンスペースにすべての行が収まるようにします


代替案

sedとは異なり、すべての選択肢はプロセスを開始するために最後の行に到達する必要はありません

withbash、遅い

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

withPerlsed-like speed

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

withtrsedより高速、1文字のみで置換可能

tr '\n' ' ' < file

withpastetr-のような速度、1文字のみで置換可能

paste -s -d ' ' file

withawktr-like speed

awk 1 ORS=' ' file

"echo $(<file)"のような他の代替方法は低速で、小さなファイルでのみ動作し、ファイル全体を処理してプロセスを開始する必要があります。


sed FAQ 5.1 からの長答

5.10。\nエスケープを使用して改行を一致または削除できないのはなぜですか
シーケンス?\nを使用して2行以上の行を照合できないのはなぜですか?

\ nは行末の改行と決して一致しません。
改行は、行が配置される前に常に削除されます
パターンスペース。 2行以上をパターンスペースに入れるには、次を使用します。
「N」コマンドまたは類似のもの(「H; ...; g;」など)。

Sedは次のように機能します。sedは一度に1行ずつ読み取り、
改行を終了し、パターンスペースに残されたものを置きます。
sedスクリプトは、アドレス指定または変更が可能で、パターンスペースが
が出力され、stdout(またはファイル)に改行が追加されます。もし
パターンスペースは「d」または「D」で完全または部分的に削除されます。
このような場合、改行はnot追加されます。したがって、次のようなスクリプト

  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         

末尾の改行が削除されるためbefore
行はパターンスペースに挿入されます。上記のタスクを実行するには、
代わりに次のスクリプトのいずれかを使用します。

  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          

GNU sed以外のsedのバージョンには、サイズの制限があるため
パターンバッファ、ここではUnix 'tr'ユーティリティを優先します。
ファイルの最後の行に改行が含まれている場合、GNU sedが追加されます
その出力の改行は、他のすべてを削除しますが、trは
すべての改行を削除します。

2行以上のブロックを一致させるには、3つの基本的な選択肢があります。
(1) 'N'コマンドを使用して、次の行をパターンスペースに追加します。
(2)「H」コマンドを少なくとも2回使用して、現在の行を追加します
ホールドスペースに移動し、ホールドスペースから行を取得します
x、g、またはGを使用。または(3)アドレス範囲を使用します(上記のセクション3.3を参照)
2つの指定されたアドレス間の行を一致させます。

選択肢(1)および(2)は、パターン空間に\ nを挿入します。
は、必要に応じてアドレス指定できます( 's/ABC\nXYZ/alphabet/g')。一例
「N」を使用して行ブロックを削除することは、セクション4.13に記載されています。
( "specific連続した行のブロックを削除するにはどうすればよいですか?")。この
例は、deleteコマンドを何かに変更することで変更できます
その他、「p」(印刷)、「i」(挿入)、「c」(変更)、「a」(追加)、
または 's'(代替)。

選択肢(3)はパターン空間に\ nを入れませんが、does
連続した行のブロックと一致するため、一致しない可能性があります
探しているものを見つけるために\ nも必要です。 GNU sed以来
バージョン3.02.80は、次の構文をサポートするようになりました。

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

従来の「/ from here /、/ to there/{...}」範囲に加えて
アドレス、\ nの使用を完全に回避できる場合があります。

455
hdorio

もっと短いawkの選択肢:

awk 1 ORS=' '

説明

Awkプログラムは、条件付きコードブロックからなる規則で構成されています。

condition { code-block }

コードブロックを省略すると、デフォルトの{ print $0 }が使用されます。したがって、1は真の条件として解釈され、print $0は各行に対して実行されます。

awkは入力を読み込むとき、デフォルトでは改行であるRS(Record Separator)の値に基づいてレコードに分割します。したがって、awkはデフォルトで入力を行単位で解析します。分割には、入力レコードからRSを取り除くことも含まれます。

これで、レコードを印刷するとき、ORS(Output Record Separator)が追加され、デフォルトは改行になりました。そのため、ORSをスペースに変更することで、すべての改行がスペースに変更されます。

203
Thor

gnu sedには、NULLで区切られたレコード(行)用のオプション-zがあります。あなただけ呼び出すことができます:

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

Perl バージョンはあなたが期待したように動作します。

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

コメントで指摘されているように、これが適切に編集されていることは注目に値します。あなたの 正規表現 があなたが思ったほど賢くない場合に備えて、-i.bakはあなたに元のファイルの置き換えをする前にあなたに与えるでしょう。

80
ire_and_curses

誰がsedを必要としますか?これがbashのやり方です。

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

ファイル全体をメモリに読み込まずに、awkを使ってすべての改行をスペースに置き換えるには、次のようにします。

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

最終改行が必要な場合

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

スペース以外の文字を使用することができます。

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

コマンドです。

シンプルで使いやすいです。

20
Dheeraj R

三つの事。

  1. tr(またはcatなど)は絶対に必要ありません。 (GNU)sedと(GNU)awkを組み合わせると、必要なテキスト処理の99.9%を実行できます。

  2. stream!=行ベースedは行ベースのエディタです。 sedは違います。違いの詳細については sedの講義 を参照してください。ほとんどの人がsedをラインベースであると混同します。なぜなら、デフォルトではSIMPLEマッチのパターンマッチングがそれほど貪欲ではないからです。グローバルコマンドで指定されていない限り、一致した場合に一致します。グローバルコマンドがSTREAMベースではなくラインベースであれば、一度にラインだけが評価されるため、グローバルコマンドもありません。 edを実行してみてください。違いに気付くでしょう。 edは、(forループのように)特定の行を反復処理したい場合には非常に便利ですが、ほとんどの場合はsedが必要です。

  3. それが言われている、

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

    GNU sedバージョン4.2.1ではうまく動きます。上記のコマンドは、すべての改行をスペースに置き換えます。入力するのは醜くて少し面倒ですが、それでもうまくいきます。 {}は、健全性の理由で含まれているだけなので、除外することができます。

20
brent saner

答え:ラベル...

sedを使って改行(\ n)を置き換えるにはどうすればいいですか?

...は、コマンドラインでfreebsd 7.2では機能しません。

(echo foo; echo bar)| sed ':a; N; $!ba; s/\ n//g'
sed:1: ":a; N; $!ba; s/\ n// g":未使用のラベル' a; N; $!ba;/\ n//g'
foo
bar

しかし、sedスクリプトをファイルに入れるか、または-eを使用してsedスクリプトを「ビルド」しても問題ありません。

>(echo foo; echo bar)| sed -e:-e N -e '$!ba' -e '/\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

おそらくOS Xのsedは似ています。

12
Juan

xargs を使用できます。

seq 10 | xargs

または

seq 10 | xargs echo -n
10

わかりやすいソリューション

私はこの問題を抱えていました。キッカーは私がBSD(Mac OS X)とGNU(Linuxと Cygwinsedtrで動作するための解決策が必要だったということでした:

$ 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、およびBSDUTF-8 サポートなし、または不安定な端末でも動作します。

  1. 改行を別の文字と交換するにはtrを使用してください。

    NULL\000または\x00)は、UTF-8サポートを必要とせず、使用される可能性も低いので、Niceです。

  2. sedを使用してNULLを一致させる

  3. 必要ならばtrを使って余分な改行を入れ替えます。

10
CoolAJ86

私はエキスパートではありませんが、sedでは、最初に次の行をパターンスペースに追加する必要があると思います。bijは "N"を使用します。 sed&awk (Dale Dougherty and Arnold Robbins; O'Reilly 1997; page 107 in preview )の "Advanced sed commands"のセクション "Multiline Pattern Space"より:

Multiline Next(N)コマンドは、新しい行の入力を読み取り、それをパターンスペースの内容に追加することによって、複数行のパターンスペースを作成します。パターンスペースの元の内容と新しい入力行は改行で区切られています。埋め込まれた改行文字は、エスケープシーケンス "\ n"によってパターン内で一致させることができます。複数行のパターンスペースでは、メタ文字 "^"はパターンスペースの最初の文字と一致し、埋め込まれた改行の後の文字とは一致しません。同様に、 "$"はパターンスペースの最後の改行のみに一致し、埋め込まれた改行には一致しません。 Nextコマンドが実行された後、スクリプト内の後続のコマンドに制御が渡されます。

man sedから:

[2アドレス] N

次の行の入力をパターンスペースに追加します。埋め込まれた改行文字を使用して、追加された素材と元の内容を区別します。現在の行番号が変わることに注意してください。

私は これを使用 (複数の)フォーマットが正しくないログファイルを検索するために使用します。検索文字列は "みなしご化された"次の行にあります。

9
Arjan

上記の "tr"の解決策に対応して、Windows上で(おそらくGnuwin32バージョンのtrを使用して)提案された解決策は以下のとおりです。

tr '\n' ' ' < input

私のために働いていませんでした、それはエラーであるか、実際には何らかの理由で\ n w/''を交換しました。

Trの別の機能を使うと、 "delete"オプション-dはうまくいきました:

tr -d '\n' < input

または '\ n'ではなく '\ r\n'

6
John Lawler

私は、trを使って改行をタブに置き換え、次にタブを私が望むものに置き換えることによって、改行を回避するためにハイブリッドアプローチを使いました。この場合、 "
"私はHTMLブレークを生成しようとしているので。

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

状況によってはRSを他の文字列や文字に変更できるかもしれません。このように、\ nはsub/gsubに対して利用可能です。

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

シェルスクリプトの威力は、ある方法でそれを実行する方法がわからない場合は、別の方法で実行できることです。単純な問題に対して複雑な解決策をとるよりも、考慮すべきことがたくさんあります。

Gawkが遅いこと、そしてファイルをメモリに読み込むことに関しては、私はこれを知りませんが、私にとってgawkは一度に1行で動作するように見え、非常に高速です(他のものほど速くはありません)しかし、書いてテストする時間も重要です。

私はMB、さらにはGBのデータを処理しますが、私が見つけた唯一の制限は行サイズです。

5
mor

防弾ソリューション。バイナリデータセーフでPOSIX準拠、遅いです。

POSIX sedPOSIXテキストファイル および POSIX行 の定義に従って入力する必要があるため、NULLバイトと長すぎる行は使用できず、各行は改行(最後の行を含む)で終わる必要があります。ライン)。これは、任意の入力データを処理するためにsedを使用するのを難しくします。

次の解決策はsedを避け、代わりに入力バイトを8進コードに変換してから再びバイトに変換しますが、8進コード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シェルコマンド言語odtrgrepread[printf

read[、およびprintfは、少なくともbashに組み込まれていますが、おそらくPOSIXでは保証されていないため、プラットフォームによっては、各入力バイトが1つ以上の新しいプロセスを開始し、処理が遅くなる可能性があります。一言で言えばこの解決策は約50キロバイト/秒に達するだけなので、大きなファイルには適していません。

Ubuntu(bash、dash、およびbusybox)、FreeBSD、およびOpenBSDでテスト済み。

5

あなたはxargsを使うことができます - それはデフォルトでスペースで\nを置き換えます。

しかし、あなたの入力がunterminated quoteの場合を問わず、それは問題を抱えているでしょう。特定の行の引用符が一致しない場合.

4
cnst

私が特に好きな解決策は、ホールドスペースにすべてのファイルを追加し、ファイルの終わりにすべての改行を置き換えることです。

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

しかし、誰かが私に言ったいくつかのsedの実装ではホールドスペースは有限である可能性があります。

3
brandizzi

Awkを使う:

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

改行を任意の文字列に置き換え、最後の改行も置き換えます

純粋な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>
3

「普通の」置換の後に改行を入れるのは sed です。最初に改行文字を削除し、それからあなたの指示に従って処理し、そしてそれは改行を導入します。

sed を使用すると、各入力行について、トリムされた後の行の「末尾」(改行文字ではなく)を、任意の文字列に置き換えることができます。しかし、 sed は異なる行を出力します。たとえば、「行末」を「===」に置き換えたいとします(単一のスペースに置き換えるよりも一般的です)。

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

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

改行文字を文字列に置き換えるには、前述のように非効率的に tr を使用して改行文字を "特殊文字"に置き換え、次に sed を使用して置き換えることができます。あなたが望む文字列を持つその特別な文字。

例えば:

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~$
3
Robert Vila

空行を削除するには:

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

別のGNUsedメソッド、 Zsolt Botykai 's answer とほぼ同じですが、これはsedを使用しますあまり使用されないytransliterate)コマンド。これは1バイトのコード(末尾のg)を保存します。

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

ysよりも速く(おそらくtrの速度で、20倍速く)実行されることを望みますが、GNU sed v4.2.2ysよりも遅い4%です。


よりポータブルBSDsedバージョン:

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

Mac OS X(FreeBSD sedを使用)の場合

# 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
3
bashfu

この方法も使えます

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行目の交換の間に、2はホールドスペースに行き、1はパターンスペースに行き、そしてGがホールドスペースをパターンスペースに追加し、そしてhがそれにパターンをコピーしそして置換がなされそして削除される。この操作はeof​​に達するまで続けられ、正確な結果が表示されます。

2
Kalanidhi

@OP、ファイル内の改行を置き換えたい場合は、dos2unix(またはunix2dox)を使用することができます。

dos2unix yourfile yourfile
2
ghostdog74

Allowedを使用して検索して置換します\ n

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

マーカー

になる

#マーカーコメント

マーカー

1
Proximo
sed '1h;1!H;$!d
     x;s/\n/ /g' YourFile

これは巨大なファイル(バッファ制限)では機能しませんが、ファイルを保持するのに十分なメモリがあれば非常に効率的です。 (@hilojackの良いコメントの後に訂正H-> 1h;1!H

読み込み中に新しい行を変更する別のバージョン(より多くのCPU、より少ないメモリ)

 sed ':loop
 $! N
 s/\n/ /
 t loop' YourFile
1
NeronLeVelu

あなたがWindowsの行末を処理しなければならないことに十分不幸なら、あなたは\r\nを削除する必要があります。

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

私はこの答えを投稿しました。私のUnixマシンではうまく動作しない上記のほとんどのsedの推奨例を試してみて、エラーメッセージLabel too long: {:q;N;s/\n/ /g;t q}が表示されたためです。最後に私は私の要求をし、そしてそれ故にすべてのUnix/Linux環境で働くここで共有しました: -

line=$(while read line; do echo -n "$line "; done < yoursourcefile.txt)
echo $line |sed 's/ //g' > sortedoutput.txt

最初の行はファイルyoursourcefile.txtからすべての新しい行を削除し、単一行を生成します。そして2番目のsedコマンドは、そこからすべてのスペースを削除します。

標準テキストエディタ を使用することもできます。

printf '%s\n%s\n%s\n' '%s/$/ /' '%j' 'w' | ed -s file

注:これは結果をfileに保存します。

sedと同様に、この解決法は最初にファイル全体をメモリにロードしなければならないという難点があります。

0
Thor

これはうまくいくかもしれません(GNU sed)。

sed 'H;$!d;x;:a;s/^((.).*)\2/\1 /;ta;s/.//' file

Hコマンドは、パターンスペースの前に改行を追加してから、結果をホールドスペースに追加します。通常のsedの流れは、各行から次の改行を削除することです。したがって、これはホールドスペースの先頭に改行を導入し、ファイルの残りの部分を複製します。ファイルがホールドスペースにまとめられたら、ホールドスペースをパッテンスペースと交換してから、パターンマッチングを使用してすべての元の改行をスペースに置き換えます。最後に、導入された改行を削除してください。

これにはsedコマンド内で実際に改行文字列を入力しないという利点があります。

0
potong