두 개의 문자열 일치가 포함된 줄 삭제

두 개의 문자열 일치가 포함된 줄 삭제

다음 파일에서 defAND(라인 2 및 4)가 포함된 모든 라인을 제거하려면 어떻게 해야 합니까? jkl해당 일치 항목이 필드의 하위 문자열 일치에도 작동하도록 하고 싶습니다. 파일의 필드는 공백으로 구분됩니다.

$ cat test2.txt 
1. abc def ghi
2. def ghi jkl
3. jkl mno pqr
4. jkl def stu
5. vwx yza bcd

나는 부울 OR( )을 사용하여 \|이 작업을 수행했습니다.

$ sed '/def.*jkl\|jkl.*def/d' test2.txt 
1. abc def ghi
3. jkl mno pqr
5. vwx yza bcd

AND예를 들어 더 간단한 부울 구문이 있습니까 $ sed '/defANDjkl/d'?

sed '/def&jkl/d', sed '/def&&jkl/d', 및 을 시도했지만 아무것도 작동하지 않습니다 sed '/def\&jkl/d'.sed '/def\&\&jkl/d'

답변1

구체적으로 sed다음과 같이 할 수 있습니다.

sed -e '/def/!b' -e /jkl/d

( )가 발견되지 않으면 첫 번째 e표현이 b오버플로될 것입니다(행을 인쇄하는 옵션을 전달하지 않았기 때문에 -n). 발견되면 두 번째 요소가 오버플로됩니다. 따라서 결국 및 가 모두 발견된 경우에만 행이 삭제됩니다.def!djkldefjkl

원하는 수의 정규 표현식을 일반화하려면 다음을 수행할 수 있습니다.

sed '
  /regexp1/!b
  /regexp2/!b
  /regexp3/!b
  d'

\|표준어는 아니니 참고해주세요기본 정규식(BRE) 연산자. 이를 지원하는 구현은 거의 없습니다 sed. 표준 BRE에는 OR이나 AND 연산자가 없습니다. 표준 ERE(확장 정규식, sed -E많은 sed구현이 그렇듯이)는 OR( |)를 지원하지만 AND는 지원하지 않습니다.

이것완전 개방구현에는 sedAND 연산자( &) 가 있습니다.향상된-A정규식을 사용 하거나 활성화 -X하지만 다음을 수행해야 합니다.

sed -A '/.*def.*&.*jkl.*/d'

A&B및 둘 다 일치하는 문자열에 대한 일치 로 .AB

sedPerl과 유사한 정규식 구현(예: sed -Past-open 또는 sed -Rwith )을 지원 함으로써 ssed예측 연산자를 사용할 수 있습니다.

sed -P '/^(?=.*def)(?=.*jkl)/d'

(?=...)뒤에 ( ), 임의 개수의 문자 ( .*), 그 뒤에 def임의 개수의 문자 뒤에 ( ) 가 오는 경우 줄의 시작 부분과 일치합니다 jkl.

grep이것보다 더 이상 지원되는 구현이 -P없으므로 sed다음과 같습니다.

grep -vP '^(?=.*def)(?=.*jkl)'

휴대성이 더욱 좋아질 것입니다.

답변2

부분 문자열 일치도 제거 기준이 된다고 명시했으므로 다음 awk절차가 작동합니다.

~$ awk '!(/def/ && /jkl/)' test.txt
1. abc def ghi
3. jkl mno pqr
5. vwx yza bcd

이렇게 하면 다음과 같은 줄만 인쇄됩니다.아니요def"행이 합계 와 일치" 조건이 jkl충족됩니다.

꼭 필요한 경우 sed적응할 수 있습니다.답변: Stéphane Chazelas:

~$ sed -e '/def/!b' -e '/jkl/d' test.txt 
1. abc def ghi
3. jkl mno pqr
5. vwx yza bcd

답변3

대신 Perl을 사용할 수도 있습니다. 이 경우 구문은 다음보다 이해하기 쉽습니다 sed.

$ perl -ne 'print unless /def/ && /jkl/' test2.txt 
1. abc def ghi
3. jkl mno pqr
5. vwx yza bcd

또는

$ perl -ne '/def/ && /jkl/ || print' test2.txt 
1. abc def ghi
3. jkl mno pqr
5. vwx yza bcd

심지어:

$ perl -ne '(/def/ && /jkl/) ? next : print' test2.txt 
1. abc def ghi
3. jkl mno pqr
5. vwx yza bcd

답변4

Raku(이전 Perl_6) 사용

raku -ne '.put  unless .grep: all(/def/ , /jkl/);'

또는

raku -ne '.put if .grep: { !/def/ || !/jkl/ };'

또는 (@terdon의 Perl5 코드에 해당하는 Raku):

raku -ne '.put unless /def/ && /jkl/;'

또는

raku -ne '/def/ && /jkl/ || .put;'

또는

raku -ne '(/def/ && /jkl/) ?? {next} !! .put'

입력 예:

1. abc def ghi
2. def ghi jkl
3. jkl mno pqr
4. jkl def stu
5. vwx yza bcd

예제 출력:

1. abc def ghi
3. jkl mno pqr
5. vwx yza bcd

간단히 말해서, 처음 두 답변은 -neRaku의 루틴과 함께 (자동 인쇄가 아닌) 한 줄씩 플래그를 사용합니다 grep. 다음 세 가지 답변은 @terdon의 Perl(5) 답변에 해당하는 Raku입니다.

( ) 코드의 처음 두 줄은 grep두 가지 서로 다른 메커니즘을 사용하기 때문에 흥미롭습니다. 첫 번째는 조인 all(일반적으로 Raku의 컬렉션에서 호출됨)을 사용하는 반면, 두 번째 예제는 True/False를 부울린 코드 블록 grep에서 실행됩니다 {}.

처음 두 ( ) 결과 grep에 대한 좋은 변형은 루틴 ( :k, :v, :kv, :p) 에서 사용할 수 있는 추가 인수를 활용하는 것입니다 grep. 예를 들어 단순히 :p쌍("부사" 인수)을 추가하면 결과를 번호가 매겨진 쌍으로 출력하도록 코드에 지시합니다.

raku -ne '.put if .grep( { !/def/ || !/jkl/ }, :p );' 

출력 예(색인 포함):

0 => 1. abc def ghi
2 => 3. jkl mno pqr
4 => 5. vwx yza bcd

https://raku.org

관련 정보