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


1371

コマンドを使用して改行( " \n")をスペース( " ")に置き換えるにはどうすればよいsedですか?

私は失敗しました:

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

どうすれば修正できますか?


27
tr上記の例では、改行をスペースに置き換えていますが、1つの文字を1つの文字に置き換える場合にのみ、ジョブに適したツールです。上記の例では、trは機能しますが、後で制限されます。
怒り84

9
tr彼の例に示すように、質問者が各改行をスペースに置き換えたかったので、仕事に適したツールで。改行の置き換えは、独特の難解ですsedが、によって簡単に実行できtrます。これはよくある質問です。正規表現の置換の実行はによってではなくtr、によって行われsedます。これは、別の質問に対しては適切なツールです...
Mike S

3
"tr"は改行 `tr -d '\ n'`を削除することもできますが、リターンを削除してより一般的な `tr -d '\ 012 \ 015'`にすることもできます。
anthony

2
警告:「tr」は、Linuxと古いSolarisマシン(EG sol5.8)の間の文字範囲に関して異なる動作をします。例: `tr -d 'az'`および `tr -d '[az]'`。そのため、その違いのない「sed」を使用することをお勧めします。
アンソニー

2
@MikeS回答ありがとうございます。フォローtr '\012' ' 'してecho。それ以外の場合、ファイルの最後の改行も削除されます。tr '\012' ' ' < filename; echoトリックを行います。
バーニーライター2017

回答:


1514

このソリューションを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これ以外では単純な問題を使用すると問題が発生します。よりシンプルで適切なソリューションについては、この回答を参照してください。


45
@ArjanとMasi:OS XはsedGNUではなくBSDを使用しているsedため、2 つには微妙な(そしてそれほど微妙ではない)違いがある場合があります。OS Xと* nixの両方のマシンで作業している場合、これは常に苦痛です。私は通常、GNUのインストールcoreutilsfindutilsOS X上での、およびBSDのバージョンを無視します。
テレマコス

50
これ:aはレジスターではなく、ブランチラベルです。b「goto」のように機能するコマンド*のターゲットです。これをレジスターと呼ぶことは、保管場所を作成できることを意味します。「レジスタ」は2つしかありません。1つはスクリプトが使用していない「ホールドスペース」と呼ばれ、もう1つは「パターンスペース」と呼ばれます。のNコマンドは、改行と、入力ファイルの次の行をパターンスペースに追加します。[*複数のラベルとbコマンドを持つことができます。bラベル文字が追加されていないコマンドがある場合は、スクリプトの最後に分岐して次の行を読み取り、再びループします。]
さらに通知があるまで一時停止します。

108
セミコロンで区切るのではなく、コマンドを個別に実行することにより、このクロスプラットフォーム(つまりMac OS X)を実行できます。 sed -e ':a' -e 'N' -e '$!ba' -e 's/\n/ /g'
ベンジー

74
なぜこれがばかげた混乱であるかについて誰もコメントしないのはなぜですか(答え自体ではなく、提案された答えが非常に単純な問題の最良の解決策であるプログラム)。Sedは通常は問題なく走る車のように見えますが、近くの特定の通りまで車で行きたい場合は、ヘリコプターで車を持ち上げるしか方法がありません。
アークくん

12
みんな来て-動かないクレイジーで不可解なソリューションへの261の賛成票???? sedは、単一行の単純な置換に最適なツールです。他のものは単にawkを使用するだけです。やれやれ....
エド・モートン

1711

sed行ベースの入力で使用するためのものです。それはあなたが必要なことを行うことができますが。


ここでのより良いオプションはtr、次のようにコマンドを使用することです。

tr '\n' ' ' < input_filename

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

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

またはGNUバージョンを持っている場合(長いオプション付き)

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

88
Sedは行ベースであるため、改行を把握することは困難です。
アレクサンダーグラディッシュ2009

191
sedは入力の「ストリーム」で機能しますが、改行区切りのチャンクで理解します。これはUNIXツールです。つまり、1つのことを非常にうまく行っています。1つは「ファイルを行単位で処理する」ことです。他のことを行うのは難しく、バグが発生するリスクがあります。この話の教訓は、適切なツールを選択することです。あなたの質問の多くは、「このツールに本来意図されていないことをさせるにはどうすればよいですか?」という形をとっているようです。これらの質問は興味深いものですが、実際の問題を解決する過程で出て来る場合は、おそらく間違っています。
dmckee ---元モデレーターの子猫

7
@JBBrown trは、パイプラインを構築するための見過ごされがちな宝石です。
dmckee ---元モデレーターの子猫2012

70
trは素晴らしいですが、改行は単一の文字でのみ置き換えることができます。改行を文字列に置き換える場合は、別のツールを使用する必要があります
Eddy

21
@Eddy-新しい行をテキストに表示されない文字に置き換えるためにtrを使用し(バック
ティック

494

速い答え

sed ':a;N;$!ba;s/\n/ /g' file
  1. :a ラベル「a」を作成します
  2. N 次の行をパターンスペースに追加します
  3. $! ない最後の行場合はBAの 枝は、ラベル「」(に行きます)
  4. sの 代替/ \ N / 改行のための正規表現/ / スペースで/ gの グローバルマッチ(何度もそれができる限り)

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


代替案

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

bashの、遅いです

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

perlのsedの様速度を

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

TR、より速くsedは、1つの文字で置き換えることができる唯一の

tr '\n' ' ' < file

paste使用するとtrのような速度で、1文字だけで置き換えることができます

paste -s -d ' ' file

awkはTR様の速度

awk 1 ORS=' ' file

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


sed FAQ 5.10からの長い回答

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


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

Sedは次のように機能します:sedは一度に1行を読み取り、
終了する改行を切り取り、残されたものをパターンスペースに置き
、sedスクリプトがアドレス指定または変更できるようにし、パターンスペース
が印刷されると、改行を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          

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」を使用して行のブロックを削除する1つの例は、セクション4.13に記載されています
(「特定の連続する行のブロックを削除するにはどうすればよいですか?」)。この
例は、削除コマンドを
「p」(印刷)、「i」(挿入)、「c」(変更)、「a」(追加)、
または「s」(置換)などの別のものに変更することで変更できます。。

選択肢(3)は、\ nは、パターンスペースに入れていないだろうが、それはない
、それはあなたがいないのかもしれので、連続した行のブロックと一致して
も、あなたが探しているものを見つけるために、n個\必要があります。GNU sed
バージョン3.02.80 以降、次の構文がサポートされています。

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

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


6
tr素晴らしいアイデアでした、そしてあなたの全体的なカバレッジは最高品質の答えになります。
新しいアレクサンドリア

1
標準ユーティリティ)を使用するための+1 paste...その他すべて!
Totor

1
@elgaluunix.stackexchange.com/questions/4527/…を試してください
hdorio 2013

4
この回答の最も良い点は、「長い回答」がコマンドがどのようにそしてなぜ機能するかを正確に説明していることです。
pdwalker 2014年

3
これは、stackexchangeで読んだ何千もの回答の中で最も役立つかもしれません。行全体で複数の文字を一致させる必要があります。以前のsedの例では複数行をカバーしておらず、trは複数の文字のマッチングを処理できません。Perlは良さそうに見えますが、期待どおりに機能していません。できれば、この回答に数回投票します。
マイティパイル

225

より短いawkの代替:

awk 1 ORS=' '

説明

awkプログラムは、条件付きコードブロックで構成されるルールで構成されています。

condition { code-block }

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

ときにawk入力を読み取り、それはの値に基づいてレコードに分割しRS、(レコードセパレータ)デフォルトで改行されており、したがってawkデフォルトで入力ライン単位を解析します。分割にはRS、入力レコードからの除去も含まれます。

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


5
私は他の人よりもはるかに読みやすいこの単純な解決策をたくさん気に入っています
Fedir RYKHTIK 2013

8
もっと理にかなっている場合、これは効果的に次のように書くことができawk 'BEGIN { ORS=" " } { print $0 } END { print "\n"} ' file.txtます。「1」はtrue(行を処理する)およびprint(行を印刷する)として評価されます。条件をこの式に追加することもできます。たとえば、パターンに一致する行でのみ機能します: awk 'BEGIN { ORS=" " } /pattern/ { print $0 } END { print "\n"} '
michael

2
もっと簡単にできます: codeawk 'ORS = ""' file.txtcode
Udi

このようなawkを使用すると、残念ながら、ファイルの最後の改行も削除されます。`catファイルのようなサブシェルで 'tr'を使用することについては、上記のPatrick Darkの回答を参照してください。echo $(tr "\ 012" "") `トリックを行います。気の利いた。
バーニーライター

143

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

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

4
入力にnullが含まれていても、それらは(レコード区切り文字として)保持されます。
Toby Speight

6
nullがない場合、これは入力全体をロードしませんか?この場合、数ギガバイトのファイルを処理するとクラッシュする可能性があります。
Ruslan

3
@Ruslan、はい、入力全体をロードします。このソリューションは、マルチギガバイトのファイルには適していません。
JJoao 2016年

7
これは真剣に最良の答えです。他の表現は歪んでいて覚えられません。@JJoaoで使用できます-u, --unbufferedman魔法使いの状態は:「入力ファイルからのデータの最小量をロードし、より多くの場合、出力バッファをフラッシュ」。
not2qubit 2018

そう。たくさん。この。
sjas

85

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

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

コメントで指摘されているように、これが編集されていることは注目に値します。正規表現が思ったほどスマートでない-i.bak場合に備えて、置換前の元のファイルのバックアップを提供します。


23
少なくとも-i、サフィックスがないとバックアップが作成されないことを述べてください。-i.bak簡単で見苦しい間違いから-pユーザーを保護します(たとえば、入力を忘れてファイルをゼロにすること)。
テレマコス

6
@Telemachus:それは公平な点ですが、どちらの方法でも議論できます。私が言及しなかった主な理由は、OPの質問のsedの例はバックアップを作成しないため、ここでは不必要なようです。もう1つの理由は、バックアップ機能を実際に使用したことがないためです(実際、自動バックアップは煩わしいと思います)。3つ目の理由は、コマンドラインが4文字長くなることです。良くも悪くも(おそらくもっと悪い)、私は強迫的なミニマリストです。私は簡潔さを好みます。私はあなたが同意しないことを理解しています。今後もバックアップについての注意を忘れないように頑張ります。
ire_and_curses 2009

6
@Ire_and_curses:実は、あなたは私を無視することに対していまいましい議論をしました。つまり、あなたには選択の理由があり、私が選択に同意するかどうかにかかわらず、私はそれを尊重します。理由は完全にはわかりませんが、最近、この特定の事柄(-i接尾辞のないPerl のフラグ)について涙を流しています。私はすぐに取りつかれる何か他のものを見つけると確信しています。:)
Telemachus

これ-がファイル名を指定してstdinで動作しないのは本当に残念です。それを行う方法はありますか?これは、ファイルの変更を気にしないための私の頼りになる方法で、catで始まるパイプラインを使用します。
スティーブン・ルー、

@StevenLu Perlは、ファイル名が指定されていない場合、デフォルトでSTDINから読み取ります。したがって、たとえば、perl -i -p -e 's/\n//' < infile > outfile
ire_and_curses

44

誰が必要sedですか?ここにbash方法があります:

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

2
賛成票、私は通常、一番上の回答を使用しましたが、/ dev / urandomをパイプ処理すると、sedはEOFまで印刷されず、^ CはEOFになりません。このソリューションは、改行を見つけるたびに印刷します。まさに私が必要としたもの!ありがとう!
Vasiliy Sharapov

1
それならなぜですか:echo -n `cat days.txt` この投稿から
Tony

9
@Tonyは、バックティックが廃止され、猫が冗長であるためです;-)使用:echo $(<days.txt)
seumasmac

10
でも使用しませんcatwhile read line; do echo -n "$line "; done < test.txt。サブシェルに問題がある場合に役立つことがあります。
Carlo Cannas 2014年

5
echo $(<file)絞り、すべて単一のスペースだけでなく、改行に空白を:これはOPが求めているものを超えています。
グレン・ジャックマン、2015年

27

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

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

最後の改行が必要な場合:

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

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

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

END{ print ""}末尾の改行の短い代替です。
Isaac

22
tr '\n' ' ' 

コマンドです。

シンプルで使いやすい。


14
または単にtr -d '\n'スペースを追加したくない場合
spuder

21

三つのこと。

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

  2. ストリーム!=行ベース。ed行ベースのエディターです。sedではありません。違いの詳細については、sedの講義を参照してください。sedデフォルトでは、SIMPLEマッチのパターンマッチングはあまり貪欲ではないため、ほとんどの人は行ベースであると混乱しています。たとえば、パターン検索を実行して1文字または2文字で置き換える場合、デフォルトでは最初のマッチのみが置換されます。検索します(グローバルコマンドで特に指定されていない限り)。一度に行のみを評価するため、STREAMベースではなく行ベースのグローバルコマンドもありません。実行してみてくださいed。違いがわかります。ed特定の行(forループ内など)を反復処理する場合は非常に便利ですが、たいていの場合はを使用するだけですsed

  3. とはいえ、

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

    GNU sedバージョン4.2.1では問題なく動作します。上記のコマンドは、すべての改行をスペースに置き換えます。入力するのは見苦しくて少し面倒ですが、問題なく動作します。{}彼らは唯一の健全性の理由から含まれているとのは、省略することができます。


3
sed基本的なことをするのに十分な知識を持っている人として、私はそれはあなた何ができるかということよりもsedむしろ、何が起こっているかを理解することがいかに簡単であるかを言わなければなりません。使用するのに非常に苦労しているsedので、使用できる場合は、より単純なコマンドを使用します。
2014年

t q条件付きジャンプとして使用s/\n / /すると、ファイル全体をメモリに読み込まずに(スペースで始まるすべての行を結合する)などのパターンで機能します。マルチメガバイトのファイルを変換するときに便利です。
テキストシェル

リンクした記事はあなたの言っていることを反映していません
hek2mgl

これは、入力が大きい場合に受け入れられる回答よりも約800倍遅くなります。これは、入力がますます大きくなると、すべての行の代わりに実行されるためです。
2016年

13

答えは:aラベル...

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; s / \ n / / g'
foo
バー

しかし、sedスクリプトをファイルに入れたり、-eを使用してsedスクリプトを「ビルド」したりすると...

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

または...

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

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

OS Xのsedも同様です。


一連の-e引数は、MKSを使用するWindowsで機能しました。ありがとう!
JamesG、2011

12

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

私はこの問題を抱えていました。キッカーは、私は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、およびBSD上で動作してもなくて- UTF-8のサポートやくだらないターミナルで。

  1. tr改行を別の文字に置き換えるために使用します。

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

  2. sedを一致させるために使用NULL

  3. tr必要に応じて、余分な改行を入れ替えるために使用します


1
命名法に関する微妙な注記:文字\000は一般にNUL(1 L)と呼ばれ、NULL一般にゼロポインター(C / C ++)について話すときに使用されます。
sqweek


9

私は専門家ではありませんが、sed最初に次の行をパターンスペースに追加する必要があると思いますN。本sed&awk(Dale Dougherty and Arnold Robbins; O'Reilly 1997; page 107 in the preview)の「Advanced sed Commands」の「Multiline Pattern Space」セクションから:

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

からman sed

[2addr] N

埋め込まれた改行文字を使用して、次の入力行をパターンスペースに追加し、追加された素材を元のコンテンツから分離します。現在の行番号が変更されることに注意してください。

これを使用して、不適切な形式の(複数の)ログファイルを検索しました。検索文字列は、「孤立した」次の行にあります。


7

ハイブリッドアプローチを使用して、trを使用して改行をタブに置き換え、タブを必要なものに置き換えて、改行を回避しました。この場合、「
」はHTMLブレークを生成しようとしているためです。

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

6

上記の「tr」ソリューションに対応して、Windowsでは(おそらくGnuwin32バージョンのtrを使用して)、提案されたソリューションは次のとおりです。

tr '\n' ' ' < input

私にとってうまくいかなかった、それはエラーになるか、何らかの理由で実際に\ nw / ''を置き換える。

ただし、trの別の機能を使用すると、「削除」オプション-dは機能しました。

tr -d '\n' < input

または「\ n」の代わりに「\ r \ n」


3
Windowsでは、おそらくを使用する必要がありますtr "\n" " " < input。Windowsシェル(cmd.exe)は、アポストロフィを引用文字として扱いません。
キース・トンプソン、

いいえ、Windows 10 Ubuntuサブシステムでは、使用する必要がありますtr "\n\r" " " < input.txt > output.txt
user1491819

これは、Gnuwin32を使用するWindows 10で機能しますcat SourceFile.txt | tr --delete '\r\n' > OutputFile.txt。または、Gnuwin32の代わりに、Gow(WindowsのGnu)、github.com / bmatzelle / gow / wiki
Alchemistmatt

5

防弾ソリューション。バイナリデータに対して安全でPOSIXに準拠していますが、速度は遅くなります。

POSIX sedに は、POSIXテキストファイル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で組み込み関数がありますが、それはおそらくので、いくつかのプラットフォーム上では、各入力バイトが物事を遅くなる、1つ以上の新しいプロセスを開始することを可能性があり、POSIXによって保証されていません。bashでさえ、このソリューションは約50 kB / sにしか達しないため、大きなファイルには適していません。

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


5

状況によってRSは、他の文字列または文字に変更できる場合があります。このように、\ nはsub / gsubで使用できます。

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

シェルスクリプトの力は、ある方法でそれを行う方法がわからない場合、別の方法で実行できることです。そして、多くの場合、単純な問題に対して複雑なソリューションを作成するよりも、考慮すべきことが多くあります。

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

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


5

残念ながらウィンドウの行末を処理する必要がある場合は、\rとを削除する必要があります\n

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

これは、置き換えられ[た空間で、そして\rスペースで、そして\nスペースで、そして]スペースで。または文字tr -d '\r\n' <fileを削除しますが、これも要求されていることではありません。は、(文字がに隣接しているかどうかに関係なく)OPの必要性に応じて適切である可能性が非常に高い文字を削除します(このバックスラッシュ表記を理解していると想定しています)。\r\ntr -d '\r' <file\r\ntr
tripleee

4

使用できますxargs\nデフォルトではスペースに置き換えられます。

ただし、入力に大文字と小文字のいずれかが含まれている場合unterminated quote、たとえば、指定された行の引用符が一致しない場合、問題が発生します。


xargsがまたきれいに最後の行を処理します
AAAfarmclub

4

許可を使用して検索および置換します\ n

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

マーカー

なる

#マーカーコメント

マーカー


4

で簡単な解決策が見つからなかったのはなぜawkですか?

awk '{printf $0}' file

printf 元の行をスペースなどで区切る場合は、改行なしですべての行を印刷します。

awk '{printf $0 " "}' file

echo "1\n2\n3" | awk '{printf $0}'、これは私にとってはうまくいきます。@ edi9999
イタチ

申し訳ありませんが、fin printf を忘れました
edi9999

これは私のためにgit bash for windowsで機能した唯一のアプローチでした
Plato

3

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

Awkの使用:

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

2
外側の引用符を単一引用符に変更する場合は、引用符とドル記号をエスケープする必要はありません。文字 "o"は、数字の "0"と混同される可能性があるため、通常、変数名としては不適切な選択と見なされます。また、変数を初期化する必要はありません。デフォルトはnull文字列です。ただし、余分な先行スペースが必要ない場合は、次のようにしますawk '{s = s sp $0; sp = " "} END {print s}'。ただし、ファイル全体をメモリに読み込まずにawkを使用する方法については、私の回答を参照してください。
追って通知があるまで一時停止。

代わりにトールの答えをチェックしてください。これは、このアプローチを比較するよりもはるかに効率的で読みやすく、優れています(これ機能しますが)。
mschilli 2013

おい、わかりました。私の顔をこする必要はありません:-)トールの答えはとにかくページの上の方にあります(そうです)ので、何を気にしますか?
Kralyk 2013

3

私が特に気に入っている解決策は、ホールドスペースにすべてのファイルを追加し、ファイルの最後にあるすべての改行を置き換えることです。

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

ただし、一部のsed実装では、ホールドスペースが有限である可能性があると誰かが言った。


1
回答を空の文字列に置き換えると、常にHを使用してホールドスペースに追加するということは、ホールドスペースが改行で始まることを意味します。これを回避するには、使用する必要があります1h;2,$H;${x;s/\n/x/g;p}
Jeff

3

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

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

含まれる入力で不要な出力が生成されるため、これは悪い@
Steven Lu

@StevenLu:いいえ、@入力はOKです。それは%a再びエスケープされて戻ってきます。ただし、ソリューションは完全にPOSIXに準拠していない場合があります(NULLバイトは許可されていないため、バイナリデータには適しておらず、すべての行が改行で終了しているため、tr出力は実際には有効ではありません)。
ホーコンA. Hjortland

ああ。修正したようですね。簡単な操作、しかし良い仕事であるべきなのかちょっと複雑です。
Steven Lu

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

この方法も使用できます

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に達するまで続けられ、正確な結果が出力されます。


ただし、echo 'Y' | sed 'x;G;1!h;s/\n/X/g;$!d'結果としてになることに注意してくださいXY
不気味な2015年

3

Zsolt Botykaiの回答とほとんど同じですが、これはあまり使用されない(文字変換)コマンドを使用する別のGNU sedメソッドです。これにより、1バイトのコード(末尾)が節約されますsedyg

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

が(おそらく20倍の速度で)yより速く動作することを期待strますが、GNU sed v4.2.2では よりもy4%遅くなりsます。


より移植性の高いBSD sedバージョン:

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

2
BSDでは、sed yは約15%高速です。実際の例については、この回答を参照してください。
トール

また、BSDでは、sedコマンドはラベルの後に終了する必要があるので、それでsed -e ':a' -e 'N;$!ba' -e 'y/\n/ /'問題ありません。
ghoti 2018
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.