Input:
1:
aaa
bbb
2:
xxx
yyy,
zzz
3:
ccc
4:
5:
xxx
yyy
出力:
1: aaa bbb
2: xxx yyy, zzz
3: ccc
4:
5: xxx yyy
:$
要件:パターン1とパターン2の間のすべての行をマージします:$
(パターン1は含まれていますがパターン2は含まれません)。
正規表現の一致::$
試み:
sed '/:$/{n;:l N;/:$/b; s/\n/ /; bl}' | sed '/:$/!b;/:$/N;/:$/!{s/\n//g}' -E
答え1
パールの使用:
$ perl -0 -pe 's/\n+/ /g;
s/ (\d+:)/\n$1/g;
s/^\n+//;
s/ +$/\n/' input.txt
1: aaa bbb
2: xxx yyy, zzz
3: ccc
4:
5: xxx yyy
(読みやすくするためにスクリプトに改行が追加されました。そのまま実行または削除して、読み取れないコードの1行を取得できます。)
- まず、1つ以上の改行のすべてのインスタンスを空白に置き換えます(注:空の行を削除/無視する追加の有用な副作用があります)。
- 次に、すべてのインスタンスの空白を置き換えます。スペース、1つ以上の数字、
:
改行文字を含む。 - 次に、文字列の先頭のすべての先頭行を削除し、文字列の末尾のすべての末尾の空白を単一の改行に置き換えます。これは、以前のs///置換操作がすべての改行を空白に置き換えたために必要です。
この-0
オプションは、Perlに入力レコード区切り文字としてNULを使用するように指示し、入力にNULが含まれていないため、入力ファイル全体を1つの長い文字列として扱います。
Perlには、「読み取り、処理、および自動印刷」ループで1行のスクリプト全体をラップする-p
ように機能させるオプションがあります。sed
ちなみに、-n
Perlのsed-n
オプションと同じです(「読み取り、処理するが自動的に印刷しない」ループ)。
man perlrun
これらおよびオプションの詳細についてはを参照-0
してください。-p
-n
答え2
そしてawk
:
$ awk -v ORS= '/:$/{print n; n="\n"; s=""} {print s $0; s=" "} END{print n}' ip.txt
1: aaa bbb
2: xxx yyy, zzz
3: ccc
4:
5: xxx yyy
-v ORS=
レコード区切り記号のNULL値の出力/:$/{print n; n="\n"; s=""}
- 最初は空です
n
(最初の行の前に改行文字が印刷されるのを防ぐため)。 s
一致するものが見つかるたびに削除されます。
- 最初は空です
{print s $0; s=" "}
- 印刷
s
後、入力ラインが続きます。 s
次に終わらない行にのみ空白文字を使用する:
- 印刷
答え3
「サイズ調整可能」スライドウィンドウを使用できます。$!N
通常、ここでのみ条件付きP
でD
実行する必要があります。パターンスペースに行を蓄積し、パターンスペースが一致しない場合は改行を空白に置き換え、/:$/
それ以外の場合は印刷して改行として削除して繰り返します。
sed '/:$/{
:do
$!N;/:$/{
P;D
}
s/\
/ /
t do
}' infile
gnu sed
1行の構文を好む場合:
sed '/:$/{:do;$!N;/:$/{P;D;};s/\n/ /;t do}' infile
答え4
trとsedを使用する方が簡単です。
$ tr '\n' ' ' <infile | sed 's/ [0-9]/\n&/g' | sed 's/^ //'
1: aaa bbb
2: xxx yyy zzz
3: ccc
4:
5: xxx yyy
(ソートが問題にならない場合は、上記のコードから2番目のsedを省略することもできます)