답변:
grep
갈 길 이외의 도구 입니다.
예를 들어 perl을 사용하면 명령은 다음과 같습니다.
perl -ne 'print if /pattern1/ xor /pattern2/'
perl -ne
stdin의 각 줄에 주어진 명령을 실행합니다.이 경우 줄이 일치 /pattern1/ xor /pattern2/
하거나 다른 패턴이 아닌 다른 패턴과 일치하지 않으면 (인쇄 또는).
이것은 어느 순서로든 패턴에 대해 작동하며 여러 번의 호출보다 성능이 좋으며 grep
입력도 적습니다.
또는 awk와 함께 더 짧습니다.
awk 'xor(/pattern1/,/pattern2/)'
또는없는 awk 버전 xor
:
awk '/pattern1/+/pattern2/==1`
xor
는 GNU Awk에서만 사용할 수 있습니까?
/pattern1/+/pattern2/==1
ir xor
가없는 것으로 교체 할 수 있습니다 .
\b
패턴 자체에 단어 경계 ( )를 넣을 수 있습니다 ( 예 :) \bword\b
.
함께 시도 egrep
egrep 'pattern1|pattern2' file | grep -v -e 'pattern1.*pattern2' -e 'pattern2.*pattern1'
grep -e foo -e bar | grep -v -e 'foo.*bar' -e 'bar.*foo'
Direct invocation as either egrep or fgrep is deprecated
- 선호grep -E
grep
(즉 지원 -F
,-E
, -e
, -f
POSIX의 요구에 따라)입니다 /usr/xpg4/bin
. 유틸리티 /bin
는 구식입니다.
grep
Perl과 같은 정규 표현식 ( pcregrep
또는 GNU 또는 ast-open 등 grep -P
) 을 지원하는 구현을 사용하면 다음을 사용 하여 한 번의 grep
호출로 수행 할 수 있습니다 .
grep -P '^(?=.*pat1)(?!.*pat2)|^(?=.*pat2)(?!.*pat1)'
즉, 라인 일치하는 찾을 수있다 pat1
하지만 pat2
, 또는 pat2
아니지만을 pat1
.
(?=...)
그리고 (?!...)
각각 미리보고 부정적인 모습 앞서 사업자한다. 그래서 기술적으로, 대상 (의 시작 부분에 대해 위의 모습은 ^
)는 다음 있어요 제공 .*pat1
하고 다음에하지 .*pat2
, 또는와 동일 pat1
및 pat2
반대.
두 패턴을 두 번 찾을 때 두 패턴을 모두 포함하는 라인에는 적합하지 않습니다. 대신 다음과 같은 고급 펄 연산자를 사용할 수 있습니다.
grep -P '^(?=.*pat1|())(?(1)(?=.*pat2)|(?!.*pat2))'
(?(1)yespattern|nopattern)
에 대한 일치 yespattern
1
st 캡처 그룹 ( ()
위의 빈 )이 일치 하는지 여부nopattern
합니다. 이 경우 ()
일치 수단이 있음을 pat1
우리는 찾아 일치하지 않는, 그래서 pat2
(앞서 긍정적 인 모양), 우리는 찾아 하지 pat2
, 그렇지 않으면 (음수 봐 앞서를).
로 다음과 같이 sed
작성할 수 있습니다.
sed -ne '/pat1/{/pat2/!p;d;}' -e '/pat2/p'
grep: the -P option only supports a single pattern
은 적어도 내가 액세스 할 수있는 모든 시스템에서 실패 합니다. 그러나 두 번째 솔루션은 +1입니다.
grep
. pcregrep
ast-open grep에는 그런 문제가 없습니다. 나는 배수 -e
를 대체 RE 연산자로 대체 했으므로 grep
이제 GNU 에서도 작동해야합니다 .
부울 용어로 A xor B를 찾고 있습니다.
(B가 아닌 A)
또는
(A가 아닌 B)
귀하의 질문에 일치하는 줄이 표시되는 한 출력 순서에 관심이 있다고 언급하지 않는다면 A xor B의 부울 확장은 grep에서 매우 간단합니다.
$ cat << EOF > foo
> a b
> a
> b
> c a
> c b
> b a
> b c
> EOF
$ grep -w 'a' foo | grep -vw 'b'; grep -w 'b' foo | grep -vw 'a';
a
c a
b
c b
b c
sort | uniq
.
다음 예의 경우 :
# Patterns:
# apple
# pear
# Example line
line="a_apple_apple_pear_a"
이것은 순전히 수행 할 수 있습니다 grep -E
, uniq
하고 wc
.
# Grep for regex pattern, sort as unique, and count the number of lines
result=$(grep -oE 'apple|pear' <<< $line | sort -u | wc -l)
grep
Perl 정규식으로 컴파일 된 경우 다음으로 파이프하는 대신 마지막 항목에서 일치시킬 수 있습니다 uniq
.
# Grep for regex pattern and count the number of lines
result=$(grep -oP '(apple(?!.*apple)|pear(?!.*pear))' <<< $line | wc -l)
결과를 출력하십시오.
# Only one of the words exists if the result is < 2
((result > 0)) &&
if (($result < 2)); then
echo Only one word matched
else
echo Both words matched
fi
원 라이너 :
(($(grep -oP '(apple(?!.*apple)|pear(?!.*pear))' <<< $line | wc -l) == 1)) && echo Only one word matched
패턴을 하드 코딩하지 않으려면 다양한 요소 세트로 패턴을 조합하여 기능을 사용하여 자동화 할 수 있습니다.
이것은 파이프 또는 추가 프로세스가없는 함수로 Bash에서 기본적으로 수행 될 수 있지만 더 복잡하고 아마도 귀하의 질문 범위를 벗어납니다.
Big apple\n
과 가 포함되어 있으면 pear-shaped\n
출력에 두 줄이 모두 포함되어야합니다. 귀하의 솔루션은 2의 수를 얻습니다. 긴 버전은 "모두 일치하는 단어"(잘못된 질문에 대한 답변)를보고하고 짧은 버전은 아무 것도 말하지 않습니다. (3) 제안 : -o
일치하는 내용이 포함 된 줄을 숨기므로 여기에 사용하는 것은 정말 나쁜 생각이므로 두 단어가 같은 줄에 나타나는 경우를 볼 수 없습니다. … (계속)
uniq
/ sort -u
및 멋진 Perl 정규식을 사용한다고해서 실제로이 질문에 유용한 답이되는 것은 아닙니다. 그러나 그들이 그렇게해도 질문에 대답하는 데 어떻게 도움이 되는지 설명하지 않기 때문에 여전히 나쁜 대답이 될 것 입니다. ( 좋은 설명의 예는 Stéphane Chazelas의 답변 을 참조하십시오 .)
[a-z][a-z0-9]\(,7\}\(\.[a-z0-9]\{,3\}\)+
? (2) 단어 / 패턴 중 하나가 한 줄에 두 번 이상 나타나고 다른 하나는 나타나지 않으면 어떻게해야합니까? 이 단어가 한 번 나타나는 단어와 동일합니까, 아니면 여러 번 나타나는 것으로 간주됩니까?