다음과 같은 파일에서 :
...
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