OPEN STEP 4.2 OSを使用しています...現在、次のsedコマンドを使用しています。
sed -n '1,/141.299.99.1/p' TESTFILE | tail -3
このコマンドは、IPが141.299.99.1のファイル内で1つのインスタンスを検索し、その前に3行も含めます。これは、IPのすべてのインスタンスとその前の3行も検索したいという例外を除きます。そして最初だけではありません。
OPEN STEP 4.2 OSを使用しています...現在、次のsedコマンドを使用しています。
sed -n '1,/141.299.99.1/p' TESTFILE | tail -3
このコマンドは、IPが141.299.99.1のファイル内で1つのインスタンスを検索し、その前に3行も含めます。これは、IPのすべてのインスタンスとその前の3行も検索したいという例外を除きます。そして最初だけではありません。
回答:
このGNU sedの例にgrep -B3基づいて、sed移動ウィンドウを使用してエミュレートする試みを次に示します(ただし、可能であればPOSIX準拠-@StéphaneChazelasに感謝します)。
sed -e '1h;2,4{;H;g;}' -e '1,3d' -e '/141\.299\.99\.1/P' -e '$!N;D' file
最初の2つの式は、複数行パターンバッファーを準備し、最初の一致の前に先行するコンテキストが3行未満であるエッジケースを処理できるようにします。中間の(正規表現一致)式は、目的の一致テキストがパターンバッファーに波及するまで、ウィンドウの上部から行を印刷します。最終的な$!N;Dスクロールが入力の終わりに到達したときを除いて一行によって窓。
-eGNU固有ではありません。POSIX /ポータブルにするために、あなたはない必要があった後、何もすることができないとして、それを}(そして、あなたが必要とする;その前に)。
-e '1h;2,4{H;g;}' -e '1,3d'ますか?テストする非GNUシステム--posixはありません(GNU sed スイッチは気にしないようです)。
sed従来のUnix sedの子孫である家宝ツールチェストを使用して、異なる実装をテストできます。以下のためのPOSIX / Unixの仕様はsedであるpubs.opengroup.org/onlinepubs/9699919799/utilities/sed.html
grep これのより良い仕事をします:
grep -B 3 141.299.99.1 TESTFILE
-B 3手段、各試合の前に3行を印刷します。これは--、行の各グループ間で印刷されます。それを無効にするには--no-group-separator、同様に使用します。
この-Bオプションは、GNUgrepおよびほとんどのBSDバージョン(OSX、FreeBSD、OpenBSD、NetBSD)でもサポートされていますが、技術的には標準オプションではありません。
ではsed、あなたは、スライディングウィンドウを行うことができます。
sed '1N;$!N;/141.299.99.1/P;D'
それはそれを行います。しかし、注意してください- 引用されbashてい! ても拡大するという非常識な動作!!! コマンド履歴からコマンド文字列に入力すると、少しおかしくなります。set +H;この場合は、コマンドの前にプレフィックスを付けてください。それを再度有効にするには(しかし、なぜ???)、set -H後で行います。
もちろん、それはあなたが使用している場合にのみ適用されますbash-私はあなたがそうだとは思いませんが。私はあなたが作業していることをかなり確信していますcsh- (これはたまたまbashその異常な振る舞いが履歴展開をエミュレートするシェルですが、cシェルが取った極端なものではないかもしれません)。だから、おそらく\!動作するはずです。私は願います。
それはすべて移植可能なコードです:POSIXはそのように3つの演算子を説明します:(この説明が早くも2001年に存在することを確認しただけであることに注意してください)
[2addr]N\n埋め込み\newlineを使用して元のマテリアルから追加されたマテリアルを分離し、 入力の次の行(終端のewlineを除く)をパターンスペースに追加します。現在の行番号が変更されることに注意してください。
[2addr]Pパターンスペースを最初の\newlineまで、標準出力に書き込みます。
[2addr]Dパターン空間の最初のセグメントを最初の\newline から削除して、次のサイクルを開始します。
そのため、最初の行では、パターンスペースに追加の行を追加するため、次のようになります。
^line 1s contents\nline 2s contents$
次に、最初の行とそれ以降のすべての行(最後の行を除く)で、パターンスペースに別の行を追加します。したがって、次のようになります。
^line 1\nline 2\nline 3$
IPアドレスがP最初の改行までリント内で見つかった場合は、ここの1行目だけです。すべてのサイクルの終わりに、あなたはD同じことを繰り返し、残りのものからやり直します。したがって、次のサイクルは次のようになります。
^line 2\nline 3\nline 4$
...等々。IPがこれら3つのいずれかで見つかった場合、最も古いものが毎回出力されます。したがって、常に3 行先だけです。
以下に簡単な例を示します。ゼロで終わるすべての番号に対して3行のバッファーが出力されます。
seq 10 52 | sed '1N;$!N;/0\(\n\|$\)/P;D'
10
18
19
20
28
29
30
38
39
40
48
49
50
それはあなたの問題よりも似ているために0\n改行または0$パターンスペースの終わりから交互に変更する必要があるため、あなたの場合よりも少し複雑です-しかし、これはアンカーを必要とするという点で微妙に異なります-パターンスペースは絶えずシフトします。
10と52の奇数のケースを使用して、アンカーが柔軟である限り、出力も柔軟であることを示しました。完全に移植性があるので、代わりにアルゴリズムに頼って同じ結果を得ることができます:
seq 10 52 | sed '1N;$!N;/[90]\n/P;D'
そして、私のウィンドウを制限しながら検索を広げます-0から9および0から3行から2行。
とにかく、あなたはアイデアを得る。
sed '...' $filename。ちなみに-私はあなた自身の検索文字列からピリオドを残しましたが、実際にはパターン内のピリオドではありません-それらは任意の単一文字を表します。おそらく行う必要がありますoct\.oct\.oct\.oct彼らはので、それらをエスケープするだけの期間と一致します。
のオプションがないことを述べたので、Perlを使用して(たとえば)4行のウィンドウをスライドさせることができます。-Bgrep
perl -ne '
push @window,$_;
shift @window if @window > 4;
print @window if /141\.299\.99\.1/
' your_file
Rameshの答えは、同様のことをしていawkます。
シェル自体に他のgrep以外の回答と同じ基本的なアプローチを実装できます(これは、をサポートする比較的最近のシェルを想定しています=~)。
while IFS= read -r line; do
[[ $line =~ 141.299.99.1 ]] && printf "%s\n%s\n%s\n%s\n" $a $b $c $line;
a=$b; b=$c; c=$line;
done < file
または、ファイル全体を配列に丸couldみすることもできます。
perl -e '@F=<>;
for($i=0;$i<=$#F;$i++){
print $F[$i-3],$F[$i-2],$F[$i-1],$F[$i] if $F[$i]=~/141.299.99.1/
}' file
awk '/141.299.99.1/{for(i=1;i<=x;)print a[i++];print} {for(i=1;i<x;i++)
a[i]=a[i+1];a[x]=$0;}' x=3 filename
このawkソリューションでは、現在のパターンの前に常に3行が含まれる配列が使用されます。したがって、パターンが一致すると、現在のパターンとともに配列の内容が出力されます。
テスト中
-bash-3.2$ cat filename
10.0.0.1
10.0.0.2
10.0.0.3
10.0.0.4
141.299.99.1
10.0.0.5
10.0.0.6
10.0.0.7
10.0.0.8
10.0.0.9
10.0.0.10
141.299.99.1
10.0.0.11
10.0.0.12
10.0.0.13
10.0.0.14
10.0.0.15
10.0.0.16
141.299.99.1
10.0.0.17
10.0.0.18
10.0.0.19
コマンドを実行すると、出力は次のようになります。
10.0.0.2
10.0.0.3
10.0.0.4
141.299.99.1
10.0.0.8
10.0.0.9
10.0.0.10
141.299.99.1
10.0.0.14
10.0.0.15
10.0.0.16
141.299.99.1
これらのほとんどでは、/141.299.99.1/また、(例えば)と一致します141a299q99+1か141029969951ので、.正規表現で任意の文字を表すことができます。
使用すると、/141[.]299[.]99[.]1/より安全で、あなたはそれが一致していないことを確認するために正規表現全体の最初と最後に追加のコンテキストを追加することができ3141.、.12、.104など、