開始パターンと終了パターンの間の最後の行シーケンスを印刷するには?

開始パターンと終了パターンの間の最後の行シーケンスを印刷するには?

この質問に対する答え:

開始パターンと終了パターンの間の行を見つける方法は?

一致するパターン間の複数の行シーケンスは気にしません。例えば、sed -n '/startpattern_here/,/endpattern_here/p'これらのパターンが現れる間に一連の複数行が印刷される。

しかし、単に印刷したいとしましょう。最後ファイルにこれらの順序があります。 sedを使用してこれを実行できますか?そうでなければ、おそらく奇妙に思えますか?他にはありませんか?

メモ:

  • これらのシーケンスは重複しないと仮定することができる。
  • 開始および終了パターンラインしなければならない出力に含まれます。
  • 複雑さの低いパターンを想定する答えも有効です(最適ではありませんが)。

答え1

完全正規表現テストが必要な場合は、次のように動作します。

awk '/startpattern_here/ {buf="";f=1}
     f{buf=buf $0 "\n"}
     /endpattern_here/ {f=0; lastcomplete=buf}
     END{printf("%s",lastcomplete)}' file.txt

これにより、完全な開始 - 停止パターンのみが印刷されます。

テストケース:

irrelevant
irrelevant
irrelevant
startpattern_here
relevant_but_dont_show_1
relevant_but_dont_show_1
relevant_but_dont_show_1
endpattern_here

irrelevant
irrelevant
 
startpattern_here
relevant_but_dont_show_2
relevant_but_dont_show_2
relevant_but_dont_show_2
endpattern_here

irrelevant
irrelevant

startpattern_here
relevant_and_show
relevant_and_show
relevant_and_show
endpattern_here

irrelevant
startpattern_here
incomplete_dont_show

結果:

startpattern_here
relevant_and_show
relevant_and_show
relevant_and_show
endpattern_here

ノート開始モードと終了モードの出力を抑制するには、sumsルールを変更するだけです/startpattern_here/ { ... }/endpattern_here/ { ... }つまり、「終了モード」ルールを最初に配置し、END次に「開始モード」ルールを配置するだけです。

答え2

tacとawkの組み合わせ

tac file \
| awk '
   !p && /endpattern_here/   {p = 1}
    p                        {print}
    p && /startpattern_here/ {exit}
' \
| tac

答え3

そして前任者(POSIXエディタ)とてもシンプルです。

printf '%s\n' 1 '?END?' '?START?,.p' | ex -s file
  • 1ファイルの最初の行に移動します。これはファイルの最後の行である場合にEND必要です。

  • ?END?ファイルの末尾から後ろに検索して、ENDファイルに最後に表示される項目を見つけます。

  • ?START?,.pSTART前のアドレスから現在のアドレスまですべて印刷します。

printf以下は、多様性のためにhere-docsを代わりに使用する例です。

$ cat file
zdk
START
b12
END
kdn
START
000
111
END
START
ddd
$ ex -s file <<EOF
> 1
> ?END?
> ?START?,.p
> EOF
START
000
111
END

答え4

1つの方法は、単に各グループを保存し、次のグループで上書きして最後に達したときに保持したグループを印刷することです。

awk '{ 
        if(/startpattern_here/){
            a=1; 
            lines=$0; 
            next
        } 
        if(a){
            lines=lines"\n"$0
        } 
        if(/end_pattern/){
            a=0
        }
    } 
    END{
        print lines
    }' file

たとえば、次のテストファイルを使用します。

startpattern_here
line 1
line 2
line 3
end_pattern
startpattern_here
line 1b
line 2b
line 3b
end_pattern
startpattern_here
line 1c
line 2c
line 3c
end_pattern

私は得る:

$ awk '{ if(/startpattern_here/){a=1; lines=$0; next} if(a){lines=lines"\n"$0} if(/end_pattern/){a=0}} END{print lines}' file
startpattern_here
line 1c
line 2c
line 3c
end_pattern

関連情報