一致する2つのパターン間の線を探しています。開始または終了パターンが欠落している場合、その行は印刷されません。
正しい入力:
a
***** BEGIN *****
BASH is awesome
BASH is awesome
***** END *****
b
出力は次のとおりです
***** BEGIN *****
BASH is awesome
BASH is awesome
***** END *****
ここで、入力からENDパターンが欠落していると仮定します。
a
***** BEGIN *****
BASH is awesome
BASH is awesome
b
行を印刷しないでください。
私はsedを試してみました。
sed -n '/BEGIN/,/END/p' input
ENDモードがない場合は、最後の行まですべてのデータを印刷します。
どうやって解決しますか?
答え1
次のようにこれを行うことができます。
$ sed -e '
/BEGIN/,/END/!d
H;/BEGIN/h;/END/!d;g
' inp
どのように機能するかは、行の始まり/終わりの範囲に対してストレージスペースに保存することです。次に、END行が出るまで削除します。この時、私たちは私たちが持っているものが何であるかを思い出させます。 OTW、私たちは何も得ません。 HTH。
答え2
cat input |
sed '/\*\*\*\*\* BEGIN \*\*\*\*\*/,/\*\*\*\*\* END *\*\*\*\*/ p;d' |
tac |
sed '/\*\*\*\*\* END \*\*\*\*\*/,/\*\*\*\*\* BEGIN *\*\*\*\*/ p;d' |
tac
両方の順序で2つの区切り文字を見つけるtac
ために行を反転して動作します。sed
答え3
そしてpcregrep
:
pcregrep -M '(?s)BEGIN.*?END'
これは、BEGINとENDが同じ行にある場合でも機能しますが、次の場合は機能しません。
BEGIN 1 END foo BEGIN 2
END
pcregrep
最初はキャプチャされますが、2BEGIN 1 END
番目はキャプチャされません。
これを処理するには、awk
次のようにします。
awk '
!inside {
if (match($0, /^.*BEGIN/)) {
inside = 1
remembered = substr($0, 1, RLENGTH)
$0 = substr($0, RLENGTH + 1)
} else next
}
{
if (match($0, /^.*END/)) {
print remembered $0
if (substr($0, RLENGTH+1) ~ /BEGIN/)
remembered = ""
else
inside = 0
} else
remembered = remembered $0 ORS
}'
次のように入力すると:
a
BEGIN blah END BEGIN 1
2
END
b
BEGIN foo END
c
BEGIN
bar
END BEGIN
baz END
d
BEGIN
xxx
それは以下を提供します:
BEGIN blah END BEGIN 1
2
END
BEGIN foo END
BEGIN
bar
END BEGIN
baz END
どちらもBEGINから次のENDまですべてをメモリに保存する必要があります。したがって、最初の行にBEGINを含むがENDを持たない大きなファイルがある場合、ファイル全体は無意味にメモリに保存されます。
この問題を解決する唯一の方法は、ファイルを2回処理することです。もちろん、これは入力が通常のファイル(パイプではないなど)の場合にのみ実行できます。
答え4
GNU awkメソッド。開始ヘッダーが見つかったら、特定の変数を設定して結果を取得します。便宜上、一部の変数は短縮される場合があります。
$ awk '/BEGIN/{a[i++]=$0;flag=1;next};flag==1{a[i++]=$0;if($0~/END/){print_array=1; nextfile;} }; END{if(print_array) for(j=0;j<=i;j++)print a[j]}' input.txt
***** BEGIN *****
BASH is awesome
BASH is awesome
***** END *****
ENDフラグがないため、結果は期待どおりにnullです。
$ awk '/BEGIN/{a[i++]=$0;flag=1;next};flag==1{a[i++]=$0;if($0~/END/){print_array=1; nextfile;} }; END{if(print_array) for(j=0;j<=i;j++)print a[j]}' input2.txt