두 단어 중 하나만 포함하고 둘 다 포함하지 않는 줄 수를 계산하는 방법

두 단어 중 하나만 포함하고 둘 다 포함하지 않는 줄 수를 계산하는 방법

텍스트 파일( )에서 sum이라는 단어가 포함된 줄 수를 세어야 하는데 the,anpoem.txt동시에 둘 다 아님.

나는 사용해 보았습니다.

grep -c the poem.txt | grep -c an poem.txt

the하지만 총 합계 수가 an9행이면 6이라는 잘못된 답이 나옵니다.

단어 자체가 아닌 단어가 포함된 줄 수를 계산하고 싶습니다. 실제 단어만 계산되므로 and 는 the아니지만 .thereanPan

예시 파일:poem.txt

Where is the misty shark?
Where is she?
The small reef roughly fights the mast.
Where is the small gull?
Where is he?
The gull grows like a clear pirate.
Clouds fall like old mainlands.

She will Rise calmly like a dead pirate.
Eat an orange.
Warm, sunny sharks quietly pull a cold, old breeze.
All ships command rough, rainy sails.

Elvis Aaron Presley also known simply as the Elvis
He is also referred to as the King
The best-selling solo music artist of all time
He was the most commercially successful artist in many genres

He has many awards including a Grammy lifetime achievement
Elvis in the 1970s has numerous jumpsuits including an eagle one.

추가 설명: 이 시에서 or를 포함하는 행 수는 몇 개입니까 ? 그러나 and를 모두 포함하는 행은 the계산하지 마십시오 .anthean

the car is red - this counted
an apple is in the corner - not counted
hello i am big - not counted
where is an apple - counted

따라서 여기서 출력은 2가 되어야 합니다.

편집: 대소문자 구분은 걱정하지 않습니다.

강조표시된 단어의 스크린샷

최종 편집: 모든 도움에 감사드립니다. 이 문제를 성공적으로 해결했습니다. 답변 중 하나를 사용하고 일부 변경했습니다. cat poem.txt | grep -Evi -e '\<an .* the\>' -e '\<the .* an\>' | grep -Eci -e '\<(an|the)\>추가 정보를 얻기 위해 두 번째 grep을 a로 변경한 방법입니다 . 모든 도움에 다시 한번 감사드립니다! :)-c-n

답변1

perl -nE 'END {say $c+0} ++$c if /\bthe\b/i xor /\ban\b/i' file
gawk 'END {print c+0} /\<the\>/ != /\<an\>/ {++c}' IGNORECASE=1 file

각 표현식의 일치 결과를 비교하면 원하는 결과를 얻을 수 있습니다.

예를 들어 일치 결과는 \<the\>0 또는 1일 수 있습니다. 다른 일치 항목의 결과가 동일한 경우 두 정규 표현식이 모두 발견되거나 발견되지 않으며 해당 행은 계산되지 않습니다. 서로 다르다면 일치하는 항목 중 하나는 찾았으나 다른 항목은 발견되지 않았음을 의미하므로 카운터가 증가합니다.

gawk에는 다음과 같은 xor()기능이 내장되어 있습니다.

gawk 'END {print c+0} xor(/\<the\>/,/\<an\>/) {++c}' IGNORECASE=1 file

답변2

grep을 사용하세요:

cat poem.txt \
  | grep -Evi -e '\<an\>.*\<the\>' -e '\<the\>.*\<an\>' \
  | grep -Eci -e '\<(an|the)\>'

이것이 중요하다일치하는 선. 총계를 계산하는 대체 구문을 찾을 수 있습니다.성냥아래에.

분해:

먼저 grep 명령은 "an"과 "the"가 포함된 모든 줄을 필터링합니다. 두 번째 grep 명령은 "an" 또는 "the"가 포함된 줄 수를 셉니다.

c두 번째 grep에서 제거하면 -Eci모든 일치 항목이 강조 표시됩니다.

세부 사항:

  • -E옵션은 grep에 대한 확장 표현식 구문(ERE)을 활성화합니다.

  • -i옵션은 grep이 대소문자를 구분하지 않고 일치하도록 지시합니다.

  • -v옵션은 grep에게 결과를 반대로 하라고 지시합니다.아니요포함 모드)

  • -c옵션은 grep에게 라인 자체가 아닌 일치하는 라인 수를 출력하도록 지시합니다.

  • 모델:

    1. \<단어의 시작과 일치합니다(감사합니다@glenn-jackman)
    2. \>단어 끝 일치(감사합니다.@glenn-jackman)

    --> 이렇게 하면 단어가 일치하지 않는지 확인할 수 있습니다.포함하다"the" 또는 "an" (예: "pan")

    1. grep -Evi -e '\<an\>.*\<the\>'따라서 모든 라인과 일치아니요"a..."가 포함되어 있습니다.

    2. 마찬가지로 grep -Evi -e '\<the\>.*\<an\>'모든 줄을 일치시킵니다 .아니요"...an"을 포함합니다.

    3. grep -Evi -e '\<an\>.*\<the\>' -e '\<the.*an\>'3.과 4.의 조합입니다.

    4. grep -Eci -e '\<(an|the)\>'"an" 또는 "the"(공백 또는 줄의 시작/끝으로 둘러싸여 있음)를 포함하는 모든 줄과 일치하고 일치하는 줄 수를 인쇄합니다.

편집 1:@glenn-jackman이 제안한 대로 \<and \>대신 ( |^)and를 사용하세요.( |$)

편집 2:일치하는 행 수 대신 일치 수를 계산하려면 다음 식을 사용합니다.

cat poem.txt \
  | grep -Evi -e '\<an\>.*\<the\>' -e '\<the\>.*\<an\>' \
  | grep -Eio -e '\<(an|the)\>' \
  | wc -l

이는 각 일치 항목을 별도의 줄에 인쇄한 다음(다른 항목 없음) 줄 수를 계산 하는 -ogrep 옵션을 사용합니다.wc -l

답변3

다음 GNU awk프로그램은 이 문제를 해결해야 합니다:

awk '(/(^|\W)[Tt]he(\W|$)/ && !/(^|\W)[Aa]n(\W|$)/) || (/(^|\W)[Aa]n(\W|$)/ && !/(^|\W)[Tt]he(\W|$)/) {c++} END{print c}' poem.txt

c다음과 같은 경우 카운터가 증가합니다 .

  • 줄이 일치하지만 (^|\W)[Tt]he(\W|$)(첫 글자 대소문자 구분 안 함 the, 앞에 단어가 아닌 구성 요소( \W) 또는 줄 시작( ^), 뒤에 단어가 아닌 구성 요소( \W) 또는 줄 끝( $)이 옴)) 일치하지 않습니다 (^|\W)[Aa]n(\W|$)( 분리된 첫 번째 - 문자를 구분하지 않고 쓰기 an) - 또는 -
  • 선은 일치 (^|\W)[Aa]n(\W|$)하지만 일치하지 않습니다.(^|\W)[Tt]he(\W|$)

마지막으로 인쇄된 값입니다 c.

\<"단어 시작" 및 "단어 끝"으로 및 를 사용 \>하여 약간 더 짧게 만들 수 있습니다.

awk '(/\<[Tt]he\>/ && !/\<[Aa]n\>/) || (/\<[Aa]n\>/ && !/\<[Tt]he\>/) {c++} END{print c}' poem.txt

더 짧은 것은 다음과 같습니다.

awk '/\<[Tt]he\>/ != /\<[Aa]n\>/ {c++} END{print c}' poem.txt

an부등식은 합계 중 하나가 선에 나타나거나 둘 다 나타나지 않는 경우에만 참입니다 the.

and / 구성은 정규식 구문을 확장하는 GNU 확장이기 awk때문에 이 접근 방식에는 GNU가 필요합니다 (그러나 /는 다음과 같이 이해될 수도 있습니다).\W\<\>\<\>BSD 정규식).

파일을 입력 인수로 호출하는 것이 stdin에서 읽는 것을 대체하기 때문에 시도한 솔루션에 표시한 파이프라인 구성은 작동하지 않습니다. grep따라서 파이프라인의 첫 번째 부분은 눈에 띄지 않게 사라지고 출력은 전적으로 마지막 부분으로 인해 발생합니다( 발생 an, 즉 다른 말로 포함된 경우에도 마찬가지입니다.

답변4

GNU grep 및 PCRE 길이가 0인 어설션을 사용하여 이를 수행할 수 있습니다.

grep -iP '(?=.*\bthe\b)(?!.*\ban\b)|(?=.*\ban\b)(?!.*\bthe\b)' poem.txt

Where is the misty shark?
...
Eat an orange.
...

grep -ciP '(?=.*\bthe\b)(?!.*\ban\b)|(?=.*\ban\b)(?!.*\bthe\b)' poem.txt

9

Perl(원래 위치)에서도 동일한 기능을 사용할 수 있으며 GNU grep이 존재하지 않는 시스템에도 Perl이 존재할 수 있습니다.

관련 정보