一致した条件間のファイルからテキストの一部を抽出する方法

一致した条件間のファイルからテキストの一部を抽出する方法

以下のようなファイルがあります。

~PAR1~
This is Par1 line 1
This is Par1 line 2

Par Finished

~PAR2~
This is Par2 line 1
This is Par2 line 2

Par Finished

を渡すと、と の行PAR1の間にあるすべての行が取得されます。 どうすれば取得できますか? と を調べましたが、オプションが見つかりませんでした。PAR1Par Finishedawksed

答え1

ヘッダーとフッターの行が必要な場合は、sed 次のようにすると簡単です。

sed -n "/^~PAR1~$/,/Par Finished/p"

これは変数を使うと簡単に使えます

START=PAR1
sed -n "/^~$START~$/,/Par Finished/p"

最後の行を変数にすることもできます

START=PAR1
END="Par Finished"
sed -n "/^~$START~$/,/$END/p"

結果は次のようになります。

~PAR1~
This is Par1 line 1
This is Par1 line 2

Par Finished

開始行/終了行や空白行が必要ない場合は、少し複雑になります。

もっと良い方法があるかもしれませんが、私にとってはこれが効果的です:

sed -n "/^~$START~$/,/$END/ { /^~$START~$/d ; /$END/d ; /^$/d ; p }"

その結果は

This is Par1 line 1
This is Par1 line 2

答え2

行(オプションで末尾の空白行を含む)をレコード区切りとして使用しPar Finished、それを置き換えてレコードを完成させることができます。

awk -vRS='\nPar Finished\n*' -vp='PAR1' '$0 ~ p {print $0,"\nPar Finished"}' parfile
~PAR1~
This is Par1 line 1
This is Par1 line 2

Par Finished

awkをお持ちの場合はGNU、特別な変数を使用してレコードセパレータを復元できますRT(必要に応じて余分な改行を削除します)

gawk -vRS='\nPar Finished\n*' -vp='PAR1' '$0 ~ p {sub("\n*$", "", RT); print $0,RT}' parfile
~PAR1~
This is Par1 line 1
This is Par1 line 2

Par Finished

もちろん、変数 Par1単純な正規表現の範囲を使用する

awk '/PAR1/,/Par Finished/' parfile
~PAR1~
This is Par1 line 1
This is Par1 line 2

Par Finished

答え3

および十分に小さいファイル入力のgrep場合pcre

$ s="PAR1"

$ grep -oPz "(?s)[^\n]*${s}.*?\n.*?Par Finished.*?\n" ip.txt 
~PAR1~
This is Par1 line 1
This is Par1 line 2

Par Finished

パターン間に線を引くには:

$ grep -oPz "(?s)${s}.*?\n\K.*?(?=Par 終了)" ip.txt
これはPar1ライン1です
これはPar1ライン2です

変数を次のように変更するPAR2

$ s="PAR2"
$ grep -oPz "(?s)${s}.*?\n\K.*?(?=Par 終了)" ip.txt
これはPar2ライン1です
これはPar2ライン2です

参照: 複数行検索用の正規表現(grep)

関連情報