web-dev-qa-db-ja.com

awk / sedで複数回発生する可能性のある2つのマーカーパターン間の行を選択する方法

awkまたはsedを使用すると、2つの異なるマーカーパターンの間にある行を選択できますか?これらのパターンでマークされた複数のセクションが存在する場合があります。

たとえば、次のファイルが含まれているとします。

abc
def1
ghi1
jkl1
mno
abc
def2
ghi2
jkl2
mno
pqr
stu

そして、開始パターンはabcであり、終了パターンはmnoです。したがって、次のような出力が必要です。

def1
ghi1
jkl1
def2
ghi2
jkl2

Sedを使用してパターンを1回一致させています。

sed -e '1,/abc/d' -e '/mno/,$d' <FILE>

sedまたはawkに、ファイルの終わりまで繰り返し実行する方法はありますか?

112
dvai

awkをフラグとともに使用して、必要なときに印刷をトリガーします。

$ awk '/abc/{flag=1;next}/mno/{flag=0}flag' file
def1
ghi1
jkl1
def2
ghi2
jkl2

これはどのように作動しますか?

  • /abc/は、/mno/と同様に、このテキストを持つ行に一致します。
  • /abc/{flag=1;next}は、テキストflagが見つかったときにabcを設定します。次に、その行をスキップします。
  • /mno/{flag=0}は、テキストflagが見つかったときにmnoの設定を解除します。
  • 最後のflagは、デフォルトのアクションを持つパターンです。これは、print $0に対するものです。flagが1の場合、行が出力されます。

より詳細な説明と例、およびパターンが表示される場合とされない場合については、「 2つのパターン間の行を選択する方法? 」を参照してください。

171
fedorqui

sedの使用:

sed -n -e '/^abc$/,/^mno$/{ /^abc$/d; /^mno$/d; p; }'

-nオプションは、デフォルトでは印刷しないことを意味します。

パターンは、abcからmnoのみを含む行を探し、{ ... }でアクションを実行します。最初のアクションはabc行を削除します。 2番目のmno行。 pは残りの行を出力します。必要に応じて正規表現を緩和できます。 abc..mnoの範囲外の行は、単に印刷されません。

40

これはあなたのために働くかもしれません(GNU sed):

sed '/^abc$/,/^mno$/{//!b};d' file

abcmnoで始まる行の間の行を除くすべての行を削除します

17
potong
sed '/^abc$/,/^mno$/!d;//d' file

ppotong's{//!b};dより2文字良い

空のスラッシュ//は、「最後に使用した正規表現を再利用する」ことを意味します。コマンドはより理解しやすいものと同じことをします:

sed '/^abc$/,/^mno$/!d;/^abc$/d;/^mno$/d' file

この POSIXのようです

REが空の場合(つまり、パターンが指定されていない場合)、sedは、最後に適用されたコマンド(アドレスまたは代替コマンドの一部)で使用された最後のREが指定されたように動作します。

前の回答のリンクから、Solarisでkshを実行してくれたのは、これでした:

sed '1,/firstmatch/d;/secondmatch/,$d'
5
FanDeLaU

2つの一致するパターン間のテキストのみを表示 ?からのDon_crisstiの回答

firstmatch="abc"
secondmatch="cdf"
sed "/$firstmatch/,/$secondmatch/!d;//d" infile

aWKのアプリケーションよりもはるかに効率的です。 here を参照してください。

Perl -lne 'print if((/abc/../mno/) && !(/abc/||/mno/))' your_file
2
Vijay

このような何かが私のために働く:

file.awk:

BEGIN {
    record=0
}

/^abc$/ {
    record=1
}

/^mno$/ {
    record=0;
    print "s="s;
    s=""
}

!/^abc|mno$/ {
    if (record==1) {
        s = s"\n"$0
    }   
}

使用:awk -f file.awk data...

編集:O_o fedorquiソリューションは私のものよりもはるかに良い/きれいです。

1
pataluc

pattern2もpattern1と一致のときに、2つのパターン間の行を印刷するためにawkを使用しようとしました。また、pattern1行も印刷する必要があります。

例えばソース

package AAA
aaa
bbb
ccc
package BBB
ddd
eee
package CCC
fff
ggg
hhh
iii
package DDD
jjj

の出力が必要です

package BBB
ddd
eee

Pattern1がpackage BBBである場合、pattern2はpackage \w*です。 CCCは既知の値ではないため、文字通り一致させることはできません。

この場合、@scaiのawk '/abc/{a=1}/mno/{print;a=0}a' fileも@fedorquiのawk '/abc/{a=1} a; /mno/{a=0}' fileも機能しません。

最後に、私はawk '/package BBB/{flag=1;print;next}/package \w*/{flag=0}flag' fileでそれを解決することができました、ハハ

もう少し努力すると、awk '/package BBB/{flag=1;print;next}flag;/package \w*/{flag=0}' fileになり、pattern2行も印刷します。つまり、

package BBB
ddd
eee
package CCC
0
Weekend