sed または awk を使用して改行文字を「条件付き」として削除するには?

sed または awk を使用して改行文字を「条件付き」として削除するには?

複数行を含むファイルが与えられると、一部は=最後にあります。

=次の行で終わる各行をリンクしたいと思います。他の改行は変更せずにそのままにしてください。

sed1行ずつ行われているようで、これはできませんでした。したがって、改行は常に「追加」されます。

入力例:

Apple
Banana milkshake
Cherry =
Pie

次のようにする必要があります。

Apple
Banana milkshake
Cherry Pie

私はsed/以外のツールを使用するために完全にオープンですawk

答え1

使用awk:

$ awk '{ORS = sub(/=$/,"") ? "" : "\n"} 1' file
Apple
Banana milkshake
Cherry Pie

条件式を使用してORS(出力レコード区切り文字、デフォルト:改行)を空の文字列または改行に設定します。sub()行の終わりで置換が完了した場合(既存の行を削除)、true =、それ以外の場合はfalse最初の場合はORSに設定し""、そうでない場合に設定します"\n"1行が印刷されることを示します(ORS各行に選択された値を使用)。


あるいは、sedファイルがメモリと比較してそれほど大きくなく十分に小さいと仮定し、GNUとゼロで区切られた文字を使用することもできます。

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

sedファイル全体を 1 行で読み、=\nすべての項目をグローバルに置き換えます。

答え2

sedで終わる行を検出するために使用されます=。そのような行が見つかると、編集バッファの現在の行に次の行が追加され、2行を区切る改行文字が追加され、改行文字=と改行文字が削除され、関連付けられた行が印刷されます。

$ cat file
Apple
Banana milkshake
Cherry =
Pie
$ sed '/=$/ { N; s/=\n//; }' file
Apple
Banana milkshake
Cherry Pie

これは、すべてで終わる複数の連続した行を処理できないことに注意してください=。これを処理するには、プロセスを繰り返す必要があります(中間結果は一時ファイル、生ファイルに保存するか、単に同じコマンドに再パイプすることができます)。

...または以下で明示的なループを実行できますsed

sed -e ':again' -e '/=$/ { N; s/=\n//' -e 'b again' -e '}' file

テスト:

$ cat file
Apple
Banana milkshake
Pie =
with a cherry =
on top
$ sed -e ':again' -e '/=$/ { N; s/=\n//' -e 'b again' -e '}' file
Apple
Banana milkshake
Pie with a cherry on top

答え3

sed:

sed -e ':a' -e '$!N;s/=\n//;t a' -e 'P;D' file

GNU sed:

sed ':a;N;s/=\n//;ta;P;D' file

GNU awk:

awk '1' RS='=\n' ORS= file

真珠:

perl -pe 's/=\n//' file

入力の最後の行が=<newline>awkで終わるか、Perlがそれを削除すると、sedは削除されません。

答え4

=で終わる各行を次の行に関連付けたい。

修正する

awk '/=$/ {line=line $0;sub(/=$/,"",line);next}{$0= line $0;print $0;line=""} END{if (line) print line}' file
Apple
Banana milkshake
Cherry Pie

=また、次の行で終わる各行(レコード)を接続するか、=すべて次の行で終わる複数の連続した行(録音)を接続することもテストされています。 1つ以上の行が=ファイルの末尾にあるかどうか(どこでも)

このコードは:

  • コードの最初の部分(前next)は行を連結して=varに保存し、lineそれをsub()空の文字列=に置き換えます""(削除します)。
  • 2番目の部分(後ろnext)は、varの内容をline次の行(つまり現在のレコード)に関連付け、それを印刷してからvarにnull値を割り当てます。
  • ENDセクションは、レコードまたは=ファイルの末尾にあるレコードを印刷します。
  • 氏名next。ここで一致しない行は、/=$/2番目のコードブロックによって処理されます。ただし、ファイルが1行(またはそれ以上)で終わる場合、=2番目のコードブロックは実行されませんが、そのセクションの対応する行ENDを印刷できます。

たとえば、仮想レシピに次のデータを使用してすべてを味わうことができます。

cat supposed-recipe.txt 
Cherry Pie Smoothie. =
This cherry smoothie =
tastes just like...

Ingredients:
Greek yogurt, plain non-fat, =
unsweetened milk, =
unsalted cashews,  =
etc.

And also:
1 pinch salt, =
and oats.
1 teaspoon =
vanilla extract,
fresh =
lemon juice.
1 teaspoon =
cinnamon, =
and frozen =
sweet cherries.

Optional:
2 teaspoons =
syrup or honey, =
to sweeten if wanted.

...and, if you want,
1 teaspoon chia seeds =
or similar. =
awk '/=$/ {line=line $0;sub(/=$/,"",line);next}{$0= line $0;print $0;line=""} END{if (line) print line}' supposed-recipe.txt

Cherry Pie Smoothie. This cherry smoothie tastes just like...

Ingredients:
Greek yogurt, plain non-fat, unsweetened milk, unsalted cashews,  etc.

And also:
1 pinch salt, and oats.
1 teaspoon vanilla extract,
fresh lemon juice.
1 teaspoon cinnamon, and frozen sweet cherries.

Optional:
2 teaspoons syrup or honey, to sweeten if wanted.

...and, if you want,
1 teaspoon chia seeds or similar.

関連情報