web-dev-qa-db-ja.com

bashでn番目に出現した後に数行を出力します

パターンのn番目のオカレンスを検索し、パターンの後にk行を印刷する方法を探しています。この場合、awkgrepよりもうまく機能すると思いますが、適切に行う方法がわかりません...

次のテキストファイルがあるとします。

Draft  
blablablabla  
tralalalalala  
Draft  
blablablabla  
tralalalalala  
Draft  
important line 1  
important line 2  
Draft   
blablablabla   
tralalalalala  

この場合 n=3およびk=2、パターン「ドラフト」の3回目の出現に続く2行を印刷したいと思います。私の特定のケースでは、nとkは異なる場合があります。

これを行う簡単な方法ですか?

4
Mils

greptailを使用して、これを実現できます。

$ n=3
$ k=2
$ grep -m "$n" -A "$k" 'Draft' input.txt | tail -n "$k"
important line 1  
important line 2  
$ 

Grepの-m "$n"オプションは、n番目の一致後に停止するように指定し、-A "$k"は、各一致の後にk行を出力するようにgrepに指示します。次に、これをtail -b "$k"にパイプして、それらのk行のみを出力します。

1
Digital Trauma

救助するPerl:

 Perl -sne '$c++ if /Draft/;
            if ($c == $n) { print scalar <> for 1 .. $k; }
           ' -- -n=3 -k=2 < input
  • -sスイッチを解析します-n=3そして変数を作成します。
  • -n入力を1行ずつ読み取ります。
  • <>ダイヤモンド演算子は入力から読み取ります。
  • scalar は、入力から1行だけを読み取るために必要です。そうでない場合、 print は、ダイヤモンド演算子にリストコンテキストを強制し、残りのすべての行を出力します。
7
choroba

awk:3番目と4番目の「ドラフト」行の間の行を印刷します。

awk -v n=3 '/Draft/ { p = (++num == n) ; next }; p' file

行うべき最適化があります:4番目のドラフトが表示されたら終了します。

5
glenn jackman

awk経由

awk -v "k=2" -v "n=3" \
    '/^Draft/ {i++} 
    i==n-1 && x==0 {x++;next} 
    x>=1 && x<=k {print;x++} 
    x>k {exit}' foo
  • /^Draft/ {i++}インクリメントi to count Draft
  • i==n-1 && x==0 {x++; next}nndがDraftに出現する行をスキップし、xを設定して、nnd Draftの後の最初の行を出力します。
  • x>=1 && x<=k {print;x++}次のk行を出力します
  • x>k {exit}そして終了
1
A.B.
sed  -ne'/^\(.*\n\)*Draft *$/G'  \
     -e's/\n/&/3;t$' -e'N;D;:$'  \
     -e's///g;//!n;N;G;s/\n//2'  \
     -etq -e/.$/b$ -e:q -e'p;q' <in >out

important line 1
important line 2
0
mikeserv