次のファイルから:
...
Pattern2:TheWrongBar
foo
Pattern2:TheRightBar
foo
First Pattern
foo
...
Pattern2
この条件の前に発生したこの条件の最後の発生を見つける必要があります。First Pattern
Pattern2:TheRightBar
私の最初の考えは、以前の残りのファイルをすべてインポートすることでしたFirst pattern
。
sed -e '/First Pattern/,$d' myfile | tac | grep -m1 "Pattern I need to get"
このコードを最適化する方法はありませんか?
答え1
そしてawk
:
awk '/Pattern2/ {line=$0; next}; /First Pattern/ {print line; exit}' file.txt
/Pattern2/ {line=$0; next}
:パターンPattern2
が一致したら、その行を変数に保存しline
て次の行に移動します。/First Pattern/ {print line; exit}
:見つかったら、First Pattern
変数を印刷しline
て終了します。
例:
% cat file.txt
...
Pattern2:TheWrongBar
foo
Pattern2:TheRightBar
foo
First Pattern
foo
...
% awk '/Pattern2/ {line=$0; next}; /First Pattern/ {print line; exit}' file.txt
Pattern2:TheRightBar
答え2
君は走れるよ
sed '/PATTERN2/h;/PATTERN1/!d;x;/PATTERN2/!d;q' infile
仕組み:
sed '/PATTERN2/h # if line matches PATTERN2 save it to hold buffer
/PATTERN1/!d # if it doesn't match PATTERN1 delete it
x # exchange buffers
/PATTERN2/!d # if current pattern space doesn't match delete it
q' infile # quit (auto-printing the current pattern space)
PATTERN2
一部の行が一致する前に少なくとも1つの行が一致する場合にのみ終了するため、次PATTERN1
のように入力します。
1
2
PATTERN1
PATTERN2--1st
3
PATTERN2--2nd
PATTERN1
...
それは印刷されます
PATTERN2--2nd
最初のゲームで終了したい場合は、PATTERN1
以下を実行してください。
sed -n '/PATTERN2/h;/PATTERN1/!d;x;/PATTERN2/p;q' infile
上記の入力は何も印刷しません(まさに解決策がすることです)。
答え3
「最初のパターン」の行番号を見つけて、headを使用してその上の行を表示し、tacを介してパイプしてからgrepします。
head --lines=+"$(grep -nm1 "First Pattern" file | cut -d\: -f1)" file | tac | grep -m1 "Pattern2"
例えば。
head --lines=+6 file | tac | grep -m1 "Pattern2"
これはgrepで-m 1000000を使用するよりも安定しています。 OPは速度が重要だったので、実行時間を確認しました(私のシステムの)現在、他のすべての答えよりも速いようです。
wc -l file
25910209 file
time awk '/Pattern2/ {line=$0; next}; /First Pattern/ {print line; exit}' file
Pattern2:TheRightBar
real 0m2.881s
user 0m2.844s
sys 0m0.036s
time sed '/Pattern2/h;/First Pattern/!d;x;/Pattern2/!d;q' file
Pattern2:TheRightBar
real 0m5.218s
user 0m5.192s
sys 0m0.024s
time (grep -m1 "First Pattern" file -B 10000000 | tac | grep -m1 "Pattern2")
real 0m0.624s
user 0m0.552s
sys 0m0.124s
time (head --lines=+"$(grep -nm1 "First Pattern" file | cut -d\: -f1)" file | tac | grep -m1 "Pattern2")
Pattern2:TheRightBar
real 0m0.586s
user 0m0.528s
sys 0m0.160s
答え4
最も効果的な方法私として以前は:
grep -m1 "First Pattern" my_file -B 10000000 | tac | grep -m1 "Pattern2"
明らかに、この-B
オプションは一部の例では機能しませんが、grep
このソリューションで使用したものよりはるかに高速です。オプションの価値が高くなると検索効率が低下します。awk
sed
-B