在這樣的文件中:
...
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
僅當在某些行匹配之前至少有一行匹配時才會退出,因此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