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


119

2つの異なるマーカーパターン間で発生している線を使用awkするsed方法または選択するにはどうすればよいですか?これらのパターンでマークされたセクションが複数ある場合があります。

例:ファイルに以下が含まれているとします。

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

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

def1
ghi1
jkl1
def2
ghi2
jkl2

sedを使用してパターンを一度照合します:

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

どのような方法があるsedか、awk ファイルの終わりまで、繰り返しそれを行うには?

回答:


188

使用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つのパターン間の線を選択する方法を参照してください


30
パターンを含むすべてのパターンを印刷する場合は、を使用できます awk '/abc/{a=1}/mno/{print;a=0}a' file
scai 2013年

6
はい、@ scai!あるいはawk '/abc/{a=1} a; /mno/{a=0}' file-これで、パッティングaの条件を前に、/mno/我々は設定の前に、それが真(と、それを印刷)としてラインを評価しますa=0。これにより、書き込みを回避できprintます。
fedorqui 'SO stop harming' 2013

12
@scai @fedorquiパターン出力を含めると、次のことができますawk '/abc/,/mno/' file
Jotne

1
@hkasera awk '/abc/{flag=1}/mno/{flag=0}flag' fileが作る必要があります。
fedorqui 'SO stop harming' 2014

2
@EirNymは非常に異なる方法で処理できる奇妙なシナリオです。どの行を印刷しますか?おそらくawk 'flag; /PAT1/{flag=1; next} /PAT1/{flag=0}' file作るでしょう。
fedorqui 'SO stop harming' 2017

45

使用sed

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

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

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


返信と説明をありがとう!:)
dvai 2013

@JonathanLeffler使用の目的は何-e
ですか

1
@KasunSiyambalapitiya:主にそれは私がそれを使いたいという意味です。正式には、次の引数がsed実行するスクリプト(の一部)であることを指定します。スクリプト全体を含めるために複数の引数を使用する必要がある場合は、-eそのような各引数の前に使用する必要があります。それ以外の場合はオプションです(ただし明示的)。
ジョナサンレフラー、

@JonathanLefflerありがとう
Kasun Siyambalapitiya

いいね!(私はawkよりもsedの方が好きです。)複雑な正規表現を使用する場合、それらを繰り返さなくてもいいのはいいことです。「選択された」範囲の最初/最後の行を削除することはできませんか?またはd、最初に最初の一致までのすべての行にを適用し、次にd2番目の一致で始まるすべての行に別の行を適用するには?
hans_meine 2016

18

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

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

で始まる行abcと行の間の行を除くすべての行を削除しますmno



これは素晴らしいです。{//!b}防止abcし、mno出力に含まれているが、私はどのように把握することはできませんから。説明してもらえますか?
ブレンダン

1
@Brendan命令//!bは、現在の行が範囲に一致する行のいずれでもない場合に読み取り、改行してそれらの行を出力します。そうでない場合、他のすべての行は削除されます。
ポトン

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

ゴルフはポトンより2文字上手 {//!b};d

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

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

これはPOSIXのようです

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


1
2番目のコマンドも範囲であるため、2番目のソリューションは何もなくなると思います。ただし、最初の称賛。
ポトン2015

@potong true!最初のものがなぜ機能するのか、もっと研究しなければなりません。ありがとう!
Ciro Santilli郝海东冠状病六四事件法轮功

7

以前の応答のリンクから、kshSolarisで実行されている私のためにそれをしたのはこれでした:

sed '1,/firstmatch/d;/secondmatch/,$d'
  • 1,/firstmatch/d:1行目から最初にが見つかるfirstmatchまで削除します。
  • /secondmatch/,$d:の最初の出現からsecondmatchファイルの終わりまで、削除します。
  • セミコロンは、順番に実行される2つのコマンドを区切ります。

気になるのですが、なぜレンジリミッター(1,)が先に来るの/firstmatch/ですか?私はこれもまた語られるかもしれないと'/firstmatch/1,d;/secondmatch,$d'思いますか?
ルークデイビス

2
「1、/ firstmatch / d」では、「1行目から初めて「firstmatch」が見つかるまで削除する」と言っています。一方、「/ secondmatch /、$ d」では、「 'secondmatch'が最初に発生してからファイルの終わりまで削除する」と言います。セミコロンは、順番に実行される2つのコマンドを区切ります。
FanDeLaU 2018

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

これはawkとsedの両方のかなり良い代替手段であるため、perlの同等機能を知っておくと便利です。
akhan

2

このようなものは私にとってはうまくいきます:

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ソリューションは、私のソリューションよりもはるかに優れています。


3
GNUではawk if (record=1)if (record==1)、つまりdoubleです-gawk比較演算子を= 参照してください
George Hawkins

2

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

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

これは、AWKのアプリケーションよりもはるかに効率的ですこちらを参照してください


時間の比較をリンクすることは、ここではあまり意味がないと思います。質問の要件がまったく異なるため、解決策です。
fedorqui 'SO stop harming' 2015

2
回答を比較するためのいくつかの基準が必要なため、私は同意しません。SEDアプリケーションを備えているのはごくわずかです。
レオ・レオポルド・ヘルツ준 영

0

pattern2もpattern1にも一致するawk間に、2つのパターン間の線を印刷するために使用しようとしました。また、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、パターン2の行も印刷されます。つまり、

package BBB
ddd
eee
package CCC
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.