ほとんどの場合はより良いかもしれませんが、ファイルが本当に大きく、sedそのような大きなスクリプトファイル(スクリプトの約5000行以上で発生する可能性がある)を処理できない場合に備えて、ここでは単純sedです:
sed -ne:t -e"/\n.*$match/D" \
-e'$!N;//D;/'"$match/{" \
-e"s/\n/&/$A;t" \
-e'$q;bt' -e\} \
-e's/\n/&/'"$B;tP" \
-e'$!bt' -e:P -e'P;D'
これは、入力時のスライディングウィンドウと呼ばれるものの例です。これは、何かを印刷しようとする前に、-count行の先読みバッファーを$B作成することで機能します。
実際、おそらく、以前のポイントを明確にする必要があります。このソリューションの主なパフォーマンスリミッターは、間隔に直接関連します。このソリューションは、間隔サイズが大きいと遅くなりますが、間隔周波数が大きいとドンは遅くなります。言い換えれば、入力ファイルが非常に大きい場合でも、実際の間隔の発生が依然として非常にまれである場合、彼の解決策がおそらく道です。ただし、間隔サイズが比較的管理しやすく、頻繁に発生する可能性がある場合は、これが選択すべきソリューションです。
ワークフローは次のとおりです。
- 場合
$matchによって先行パターンスペースで発見され\newline、sed再帰的になりD、すべてのelete \newlineその先行して。
$match以前はパターンのスペースを完全に消去していましたが、オーバーラップを簡単に処理するために、ランドマークを残しておくとはるかにうまくいくようです。
- また
s/.*\n.*\($match\)/\1/、一度に取得してループをかわそうとしました$A/$Bが、大きい場合は、Dエレテループの方がかなり高速です。
- 次に
N、\newlineデリミタが前にある入力のext行をD取得し、/\n.*$match/最後に使用した正規表現w /を参照してもう一度エレテを選択しようとします//。
- パターンスペースが一致する場合、行の先頭で
$matchのみ一致することができます。以前の行は$matchすべて$Bクリアされています。
- そこで、
$Afterをループし始めます。
- このループの各実行は、我々がしようとします
s///ためubstitute &自体$A番目の\nパターンスペースでewline文字を、そして、成功した場合、t当社全体および- ESTたちを分岐する$A完全に上からかけてスクリプトを起動するためのスクリプトの実行- FTERバッファを次の入力行がある場合。
testが成功しなかった場合、opラベルにb戻って:t別の入力行を再帰します。fterの$match収集中にループオーバーが発生する可能性があり$Aます。
- 私たちが乗り越える場合
$match、機能ループ、そして我々はしようとするでしょうpRINT $場合、これはそれをされた場合、最後の行をし、!しようとしないs///ためubstitute &自体$B番目の\nパターンスペースでewline文字を。
- 我々はよ
t、それが成功した場合、EST、この、あまりにも、私たちはに分岐するでしょう:PRINTラベル。
- そうでない場合は、
:topに戻って、バッファーに追加された別の入力行を取得します。
- 我々はそれがために作る場合
:PRINT我々はよPその後、RINT D最初までelete \nパターンスペースにewlineとどのような遺跡でトップからスクリプトを再実行します。
それで、今回は A=2 B=2 match=5; seq 5 | sed...
:Print での最初の反復のパターンスペースは次のようになります。
^1\n2\n3$
そして、それsedはその$B前のバッファを収集する方法です。そして、収集した入力の後ろのsed出力$B-count行に出力します。この前の例与えられた、ということでしょうRINT を出力し、[ eleteこととのように見えるスクリプトパターンスペースの上部に送り返すには:sedP1D
^2\n3$
...そして、スクリプトの上部でNext入力行が取得されるため、次の反復は次のようになります。
^2\n3\n4$
したがって5、入力で最初の出現を見つけると、パターン空間は実際には次のようになります。
^3\n4\n5$
次に、Dエレテループが開始され、終了すると次のようになります。
^5$
そして、Next入力行がプルされるsedと、EOFにヒットして終了します。その時までに、Pライン1と2 のみをリントしました。
実行例を次に示します。
A=8 B=7 match='[24689]0'
seq 100 |
sed -ne:t -e"/\n.*$match/D" \
-e'$!N;//D;/'"$match/{" \
-e"s/\n/&/$A;t" \
-e'$q;bt' -e\} \
-e's/\n/&/'"$B;tP" \
-e'$!bt' -e:P -e'P;D'
それは印刷します:
1
2
3
4
5
6
7
8
9
10
11
12
29
30
31
32
49
50
51
52
69
70
71
72
99
100