-v를 grep하고 매치 후에 다음 줄을 제외시키는 방법은 무엇입니까?


14

grep 정규식과 일치하는 각 줄에 대해 두 줄을 필터링하는 방법은 무엇입니까?
이것은 내 최소한의 테스트입니다.

SomeTestAAAA
EndTest
SomeTestABCD
EndTest
SomeTestDEFG
EndTest
SomeTestAABC
EndTest
SomeTestACDF
EndTest

그리고 분명히 나는 grep -vA 1 SomeTestAA작동하지 않는 것을 시도 했습니다.

원하는 출력은 다음과 같습니다

SomeTestABCD
EndTest
SomeTestDEFG
EndTest
SomeTestACDF
EndTest

grep -v 'SomeTextAA'| 유니크?
DarkHeart

답변:


14

(PCRE) grep와 함께 사용할 수 있습니다 -P.

grep -P -A 1 'SomeTest(?!AA)' file.txt

(?!AA)너비가 0 인 네거티브 lookahead 패턴은 AA이후 가 없음 을 보장합니다 SomeTest.

테스트 :

$ grep -P -A 1 'SomeTest(?!AA)' file.txt 
SomeTestABCD
EndTest
SomeTestDEFG
EndTest
SomeTestACDF
EndTest

도트의 이스케이프 문자는 무엇입니까? Some.Test.AA처럼?
Behrooz

1
에 의해 점을 탈출 @Behrooz \.그래서 grep -P -A 1 'SomeTest\.(?!AA)' file.txtgrep -P -A 1 'SomeTest(?!\.AA)' file.txt
heemayl

이것은 OP의 경우 샘플 라인이 쌍으로 제공 SomeTest*\nEndTest되므로 grep일치하는 모든 컨텍스트를 일치 SomeTest*시키지만 SomeTestAA일치 후 한 줄의 컨텍스트를 실제로 핑 하지 않기 때문에이 특별한 경우에 작동합니다 . 입력에 몇 줄을 더 추가 한 다음 (예 : foobarEndTest줄 뒤에 줄 추가 ) 다시 시도하십시오.
don_crissti

1
@ don_crissti 사실입니다, 나는 이미 그 문제를 해결했습니다.
Behrooz

@ Behrooz-당신이 어떻게 그 문제를 해결하고 귀하의 질문에 내 의견에 대답 할 수 있습니까?
don_crissti

4

다음 은 임의의 입력에서 작동 하는 sed솔루션 ( -n자동 인쇄 기능 없음)입니다.

sed -n '/SomeTestAA/!p          # if line doesn't match, print it
: m                             # label m
//{                             # if line matches
$!{                             # and if it's not the last line
n                               # empty pattern space and read in the next line
b m                             # branch to label m (so n is repeated until a
}                               # line that's read in no longer matches) but
}                               # nothing is printed
' infile

그래서 같은 입력으로

SomeTestAAXX
SomeTestAAYY
+ one line
SomeTestONE
Message body
EndTest
########
SomeTestTWO
something here
EndTest
SomeTestAABC
+ another line
SomeTestTHREE
EndTest
SomeTestAA
+ yet another line

달리는

sed -n -e '/SomeTestAA/!p;: m' -e '//{' -e '$!{' -e 'n;b m' -e '}' -e'}' infile

출력

SomeTestONE
Message body
EndTest
########
SomeTestTWO
something here
EndTest
SomeTestTHREE
EndTest

즉, grep -A1 SomeTestAA infile선택한 행을 정확하게 제거합니다 .

SomeTestAAXX
SomeTestAAYY
+ one line
--
SomeTestAABC
+ another line
--
SomeTestAA
+ yet another line

흥미 롭군 나는 그것이 //일치 한다는 것을 몰랐다 /SomeTestAA/. 이 경우에는 부정 된 표현과 일치했을 것이라고 생각했습니다 /SomeTestAA/!. (+1)
Peter.O

@ Peter.O-감사합니다! 사양에 따라 비어있는 RE 는 항상 마지막 명령에 사용 된 마지막 RE 와 일치해야합니다 . (가) !의 일부가 아닌 RE , 그것은의 sed것.
don_crissti

3

여러 줄 영역을 단일 레코드로 보는 것이 더 좋을 것입니다. 있다sgrep 내가 많이 사용하지 않은 어떤입니다.

입력 레코드 구분 기호와 출력 레코드 구분 기호를 원하는대로 설정할 수있는 awk가 있습니다.

pat="^SomeTestAA"
awk  'BEGIN{ RS=ORS="\nEndTest\n"} !/'"$pat/" foo

대부분의 awk 프로그램은 작은 따옴표로 묶여 있지만 마지막에 큰 따옴표로 변경하여 $pat쉘 변수를 확장 할 수 있습니다.


awk -vpat="^SomeTestAA" -vRS="\nEndTest\n" 'BEGIN{ ORS=RS } $0 !~ pat' file
Peter.O

3

하나의 옵션은 사용하는 것입니다 pERL compatible regular expression grep:

pcregrep -Mv 'SomeTestAA.*\n' file

이 옵션을 -M사용하면 패턴이 둘 이상의 행과 일치 할 수 있습니다.


1
@don_crissti 두 줄이 모두 제거됩니다. OP의 사양은이 경우를 다루지 않습니다.
jimmij

OPs 샘플 및 질문이 그러한 경우를 다루지 않는 것이 분명합니다. 홀수의 연속 행이 일치하기 때문에 이것이 작동하는 방법을 알고 싶습니다. 상황에 맞는 행)과 일치하는 짝수의 연속 행이 있으면 실패합니다 (이후 컨텍스트 행을 제거하지 않습니다).
don_crissti

(GNU)가 grep이미 -P옵션을 통해 PCRE를 지원 한다고 가정하면 pcregrep? 를 사용하면 어떤 이점이 있습니까?
arielf

@arielf grep-M옵션을 지원하지 않습니다 .
jimmij

1

표준 사용 sed:

$ sed '/SomeTestAA/{ N; d; }' file
SomeTestABCD
EndTest
SomeTestDEFG
EndTest
SomeTestACDF
EndTest

sed스크립트 라인으로 입력 파일 라인을 구문 분석하고, 라인 패턴과 일치 할 때 SomeTestAA, 두 개의 sed편집 명령 Nd실행됩니다. 이 N명령은 다음 입력 행을 패턴 공간 ( sed편집 할 수 있는 버퍼 )에 추가하고 d패턴 공간을 삭제하고 다음 사이클을 시작합니다.


1

아래의 sed 명령으로 시도했지만 정상적으로 작동했습니다.

명령

sed  '/SomeTestAA/,+1d' filename

산출

SomeTestABCD
EndTest
SomeTestDEFG
EndTest
SomeTestACDF
EndTest

0

GNU sedd명령을 사용하여 줄을 삭제하고 접두사를 붙여 /pat/,+N패턴과 후속 N 줄 과 일치하는 줄을 선택할 수 있습니다. 일치하는 줄 뒤에 하나의 후속 줄만 삭제하려는 경우 N = 1입니다.

sed -e '/SomeTestAAAA/,+1d'
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.