다음 파일에서 def
AND(라인 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
!
d
jkl
def
jkl
원하는 수의 정규 표현식을 일반화하려면 다음을 수행할 수 있습니다.
sed '
/regexp1/!b
/regexp2/!b
/regexp3/!b
d'
\|
표준어는 아니니 참고해주세요기본 정규식(BRE) 연산자. 이를 지원하는 구현은 거의 없습니다 sed
. 표준 BRE에는 OR이나 AND 연산자가 없습니다. 표준 ERE(확장 정규식, sed -E
많은 sed
구현이 그렇듯이)는 OR( |
)를 지원하지만 AND는 지원하지 않습니다.
이것완전 개방구현에는 sed
AND 연산자( &
) 가 있습니다.향상된-A
정규식을 사용 하거나 활성화 -X
하지만 다음을 수행해야 합니다.
sed -A '/.*def.*&.*jkl.*/d'
A&B
및 둘 다 일치하는 문자열에 대한 일치 로 .A
B
sed
Perl과 유사한 정규식 구현(예: sed -P
ast-open 또는 sed -R
with )을 지원 함으로써 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
간단히 말해서, 처음 두 답변은 -ne
Raku의 루틴과 함께 (자동 인쇄가 아닌) 한 줄씩 플래그를 사용합니다 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