複数のパターンをGrepし、各パターンに異なる行数を印刷しますか?

複数のパターンをGrepし、各パターンに異なる行数を印刷しますか?

複数のパターンをgrep / awkしてから、最初のパターンの下に特定の数の行を印刷し、2番目のパターンの下に特定の数の行を印刷する方法を見つけようとしています。例えば

  ....
  other lines
  ....
###Pattern 1####
line 1
line 2
line 3 
 ....
 other lines
 ....
####Pattern 2####
line 1
line 2
line 3 
line 4
 ....
 other lines
 ....

だから私がしたいのは、ファイル内の2つのパターンを見つけて、最初のパターンとその下の最初の3行を印刷してから、2番目のパターンとその下の最初の4行を印刷することです。

これを行うと、私が望む出力は次のようになります。

####Pattern 1####
line 1
line 2
line 3
####Pattern 2####
line 1
line 2
line 3 
line 4

更新された必須出力 あまりにも明確に説明する前にお詫び申し上げます。複数のパターンがある可能性があります。だから私が達成したいのは、次のような結果です。

####Pattern 1####
line 1
line 2
line 3
####Pattern 2####
line 1
line 2
line 3 
line 4
-----
####Pattern 1####
line 1
line 2
line 3
####Pattern 2####
line 1
line 2
line 3 
line 4
-----
 and so on

答え1

sed -ne'/pattern1/{:1' -e'$p;N;s/\n/&/[num]; to' -eb1 -e\} \
     -e'/pattern2/{:2' -e'$p;N;s/\n/&/[num]; to' -eb2 -e\} \
     -ed -e:o -eh      -e'y/\n-/-\n/;s/[^-]*//g' -e'H;x;p'

-一致ブロックの後に改行があるだけに、多くのダッシュが印刷されます。したがって、各パターン1の一致の後に4行、各パターン2の一致の後に2行が必要な場合は、パターン1ブロックの末尾に4つのハイフンがあり、パターン2ブロックの最後に2つのハイフンがあります。各ブロックの間に線があります。すべて本当です。とは別に各尾の収集中に最後の行が見つかった場合 - この場合、最後の行とパターンマッチの間のすべての内容が印刷されますが、ハイフンは追加されません。

上記のスクリプトのコードの多くはsedかなり重複していることがわかります。基本的には、すべての可能な一致に対して同じタイプのループを実装します。上記のように、スクリプトを素晴らしくsedすることは非常に簡単な構文規則です。sedつまり、sed構文は非常に基本的なので、スクリプト可能なsedスクリプトを書くのは簡単な問題です。

たとえば、この操作は、必要な数のパターンに関連付けられている次の行数を処理するように簡単にパラメータ化できます。

amatch(){  sed ${2:+"-ne$(n=0;                   \
    while  [ "$#" -gt "$((!!(n+=1)))" ];         \
    do     printf "\n/%s/{:$n\n\t%s;to\n\t%s\n}" \
                  "$1" "\$p;N;s/\n/&/$2" "b$n";  \
           shift 2;                              \
    done;  printf "\nd;:o\n\t%s\n\t%s\n\tH;x;p"  \
                  'h;y/\n-/-\n/' 's/[^-]*//g'    \
)"}; }

amatch()2つ以上の引数で呼び出されるたびに、上記sedのスクリプトを作成し、各ペアに対してループを作成します。

したがって、まずsubshel​​lでスクリプトをビルドして印刷し、sedstdinsedに対して実行します。

だから私がするとき:

seq 30 | amatch \[45] 5 1$ 2

シェルのwhileループは、以下のようにコマンド置換スクリプトを組み合わせて印刷します。

/[45]/{:1
    $p;N;s/\n/&/5;to
    b1
}
/1$/{:2
    $p;N;s/\n/&/2;to
    b2
}
d;:o
    h;y/\n-/-\n/
    s/[^-]*//g
    H;x;p

sed標準入力と印刷について評価します。

1
2
3
--
4
5
6
7
8
9
-----
11
12
13
--
14
15
16
17
18
19
-----
21
22
23
--
24
25
26
27
28
29
-----

答え2

よりエレガントな方法があることは間違いありませんが、これは1つのアプローチです。

# awk '/Pattern 1/{for(c=0;c<4;c++){print;getline}}/Pattern 2/{for(c=0;c<5;c++){print;getline}}' foo
###Pattern 1####
line 1
line 2
line 3
####Pattern 2####
line 1
line 2
line 3
line 4
#

もっとエレガントに:

# awk '/Pattern 1/{c=4}/Pattern 2/{c=5}{while(c-->0){print;getline}}' foo
###Pattern 1####
line 1
line 2
line 3
####Pattern 2####
line 1
line 2
line 3
line 4
#

一致するセットの下に5つのハイフンを表示するには、次のようにします。

# awk '/Pattern 1/{c=4}/Pattern 2/{c=5}{while(c-->0){print;getline;x=1}if(x){print "-----";x=0}}' foo
###Pattern 1####
line 1
line 2
line 3
-----
####Pattern 2####
line 1
line 2
line 3
line 4
-----
#

または、最後に「------」を使用してください。

# awk '/Pattern 1/{c=4}/Pattern 2/{c=5}{while(c-->0){print;getline}}END{print "-----"}' foo
###Pattern 1####
line 1
line 2
line 3
####Pattern 2####
line 1
line 2
line 3
line 4
-----
#

関連情報