複数のパターンを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
のスクリプトを作成し、各ペアに対してループを作成します。
したがって、まずsubshellでスクリプトをビルドして印刷し、sed
stdinsed
に対して実行します。
だから私がするとき:
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
-----
#