grep을 사용하여 두 단어 중 하나만 포함하고 둘 다 포함하지 않는 줄을 검색하려면 어떻게 해야 합니까? [복사]

grep을 사용하여 두 단어 중 하나만 포함하고 둘 다 포함하지 않는 줄을 검색하려면 어떻게 해야 합니까? [복사]

"word1" XOR "word2"가 포함된 줄을 텍스트 파일에서 검색하고 싶습니다. 따라서 word1, word2를 포함하는 행을 출력해야 하지만 이 두 단어를 포함하는 행은 출력하지 않아야 합니다. XOR을 사용하고 싶지만 Linux 명령줄에서 작성하는 방법을 모르겠습니다.

나는 시도했다:

grep 'word1\|word2' text.txt
grep word1 word2 text.txt
grep word1 text.txt | grep word2
grep 'word1\^word2' text.txt

등이 있었지만 모두 실패했습니다.

답변1

GNU 사용 awk:

$ printf '%s\n' {foo,bar}{bar,foo} neither | gawk 'xor(/foo/,/bar/)'
foofoo
barbar

또는 휴대용:

awk '((/foo/) + (/bar/)) % 2'

지원( grepPCRE -P):

grep -P '^((?=.*foo)(?!.*bar)|(?=.*bar)(?!.*foo))'

그리고 sed:

sed '
  /foo/{
    /bar/d
    b
  }
  /bar/!d'

foo전체 단어(예: nor barin foobar또는 in) 만 고려하려는 경우 barbar단어를 분리하는 방법을 결정해야 합니다. 구현된 -w많은 옵션 과 같이 문자, 숫자, 밑줄을 제외한 문자로 구성된 경우 다음 grep과 같이 변경할 수 있습니다.

gawk 'xor(/\<foo\>/,/\<bar\>/)'
awk '((/(^|[^[:alnum:]_)foo([^[:alnum:]_]|$)/) + \
      (/(^|[^[:alnum:]_)bar([^[:alnum:]_]|$)/)) % 2'
grep -P '^((?=.*\bfoo\b)(?!.*\bbar\b)|(?=.*\bbar\b)(?!.*\bfoo\b))'

/ 를 단어 경계로 지원하는 GNU와 같은 구현이 sed없으면 이것이 약간 복잡해지기 때문입니다 .sedsed\<\>awk

답변2

grep 'word1\|word2' text.txtword1또는 가 포함된 행을 검색합니다 word2. 여기에는 두 가지를 모두 포함하는 행이 포함됩니다.

grep word1 text.txt | grep word2word1및 가 포함된 행을 검색합니다 word2. 두 단어가 겹칠 수 있습니다(예: foobar포함 fooob). 두 단어가 포함된 행을 검색하는 또 다른 방법(겹치지 않는 방식으로만)은 어느 순서로든 검색하는 것입니다.grep 'word1.*word2\|word2.*word1' text.txt

grep word1 text.txt | grep -v word2word1을 포함하지만 포함하지 않는 행을 검색합니다 word2. 이 -v옵션은 grep에게 일치하지 않는 줄을 유지하고 일치하는 줄을 삭제하도록 지시합니다. 이렇게 하면 원하는 결과의 절반을 얻을 수 있습니다. 대칭 검색을 추가하면 정확히 특정 단어를 포함하는 모든 줄을 얻을 수 있습니다.

grep word1 text.txt | grep -v word2
grep word2 text.txt | grep -v word1

또는 두 단어 중 하나가 포함된 줄부터 시작하여 두 단어가 모두 포함된 줄을 삭제할 수도 있습니다. 위의 구성 요소를 고려하면 단어가 겹치지 않으면 쉽습니다.

grep 'word1\|word2' text.txt | grep -v 'word1.*word2\|word2.*word1'

답변3

배시 솔루션:

#!/bin/bash 
while (( $# )); do
    a=0 ; [[ $1 =~ foo ]] && a=1 
    b=0 ; [[ $1 =~ bar ]] && b=1
    (( a ^ b )) && echo "$1"
    shift
done

테스트하려면:

$ ./script {foo,bar}\ {foo,bar} neither
foo foo
bar bar

관련 정보