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