grep -w는 줄에서 첫 번째 패턴만 일치합니다.

grep -w는 줄에서 첫 번째 패턴만 일치합니다.

grep -w나는 왜 (GNU 구현 버전 3.1)이 한 줄에서 특정 패턴의 첫 번째 발생과만 일치하는지 이해하려고 노력하고 있습니다 .

여기에 예가 있습니다. n1, n2및 와 일치할 것으로 예상했지만 n3첫 번째 항목에만 일치합니다.

$ echo 'n1=1 n2=2 n3=3' | grep -ow "n[0-9]=*"
n1

n2또는 OR 만 일치하도록 지시하면 n3첫 번째 항목과 다시 일치하고 무시합니다 n3.

$ echo 'n1=1 n2=2 n3=3' | grep -ow "n[23]=*" 
n2

내가 여기서 무엇을 놓치고 있는 걸까요? 이 동작에 대한 설명이 있습니까? 아니면 grep의 일종의 버그입니까?

아이디어는 다음과 일치하는 것입니다.

  1. n[0-9]단어가 아닌 문자가 앞뒤에 옵니다.
  2. n[0-9]로 시작하고 그 뒤에 임의 개수의 문자가 오고 단어가 아닌 문자로 끝나는 =부분 문자열 입니다.

예를 들어 문자열이 이면 n1=1 n2=== n3=3 n4== n5예상되는 결과는 다음과 같아야 합니다.

n1
n2===
n3
n4==
n5

밝히다:나는 이 목표가 달성 가능하다는 것을 알고 있지만 grep -ow -e 'n[0-9]' -e "n[0-9]=*"그게 요점이 아닙니다. 이 질문의 목적은 grep그것이 어떻게 작동하는지 이해하는 것입니다.

추가 테스트

n<num>=줄의 다른 위치에 추가하면 (등호 뒤의 후속 단어 문자 없이) 해당 문자도 일치하지만 다시 무시됩니다 n3=3.

$ echo 'n1=1 n2= n3=3 n4=' | grep -ow "n[0-9]=*"
n1
n2=
n4=

내가 마지막으로 발견한 것은 패턴을 해석하는 Perl 호환 정규식을 추가하면 하위 문자열에 대한 설명이 -P유지되지 않는 것 같다는 것입니다.-w"줄 끝에 와야 하거나 단어를 형성하지 않는 문자가 뒤에 와야 합니다.", n1=뒤에 문자가 있어도 일치하기 때문입니다.1, 이는 단어를 형성하는 문자("문자, 숫자, 밑줄").

$ echo 'n1=1 n2= n3=3 n4=' | grep -owP "n[0-9]=*"
n1=
n2
n3=
n4

grep -wP그래서 검색이 되는 것 같아요단어 경계대신 하위 문자열 끝에비단어 형성 문자. 다음과 같은 것 같습니다:

$ echo 'n1=1 n2= n3=3 n4=' | grep -o "\bn[0-9]=*\b"
n1=
n2
n3=
n4

답변1

잘 받았다. 이것은 버그인 것 같습니다 grep (3.4 및 3.7에서 테스트됨 GNU grep).

grep -ow "n[0-9]=*"
grep -Eow "n[0-9]=*"

첫 번째 일치 항목(또는 첫 번째 일치 항목만 반환)만 반환
하는 반면...

grep -Pow "n[0-9]=*"

...예상대로 모든 일치 항목을 반환합니다.

버그를 신고하려면 GNU grep다음을 확인하세요.여기.


그러나 나는 당신의 관찰을 확인할 수 없습니다-P-w[...] 유지된 설명이 없는 것 같습니다., 나에게(GNU grep 3.4 및 3.7) 명령은 예상대로 출력됩니다.

$ echo 'n1=1 n2= n3=3 n4=' | grep -owP "n[0-9]=*"
n1
n2=
n3
n4=

답변2

예를 들어 문자열이 이면 n1=1 n2=== n3=3 n4== n5예상되는 결과는 다음과 같아야 합니다.

n1
n2===
n3
n4==
n5

설명: 다음을 통해 달성할 수 있다는 것을 알고 있습니다.grep -ow -e 'n[0-9]' -e "n[0-9]=*"

이것에 대해서도 확실하지 않습니다.

u$ grep --version |head -1
grep (GNU grep) 2.27
u$ printf '%s\n' 'n1=1 n2=== n3=3 n4== n5' | grep -ow -e 'n[0-9]' -e "n[0-9]=*"
n1
n2===
n3
n4==
n5

그리고

a$ grep --version |head -1
grep (GNU grep) 3.4
a$ printf '%s\n' 'n1=1 n2=== n3=3 n4== n5' | grep -ow -e 'n[0-9]' -e "n[0-9]=*"
n1
n2===
n4==
n5

n3최신 grep이 어떻게 누락되었는지 확인하세요. 이것은 Ubuntu에 있으며 결과는 3.7과 동일합니다.

Busybox의 경우 대답은 다릅니다.

$ printf '%s\n' 'n1=1 n2=== n3=3 n4== n5' | busybox grep -ow -e 'n[0-9]' -e "n[0-9]=*"
n1
n2
n3
n4
n5

내 Mac의 BSD grep도 n1, n2... 등을 인쇄하지만 각각 두 번씩 인쇄합니다. 이유가 무엇이든지.

좋다스테판은 댓글에서 이렇게 말했습니다., -w이 목적으로는 이식성이 없는 것 같습니다.


아이디어는 다음과 일치하는 것입니다.

  • n[0-9]단어가 아닌 문자가 앞뒤에 옵니다.

  • n[0-9]로 시작하고 그 뒤에 임의 개수의 문자가 오고 단어가 아닌 문자로 끝나는 =부분 문자열 입니다.

당신은 Perl에서 다음과 같은 것을 구현하고 싶은 것 같습니다( =우선순위가 있도록 이 순서대로):

/ n[0-9]=*(?=\W) | \bn[0-9]\b /x

예를 들어

$ printf '%s\n' 'n1=1 n2=== n3=3 n4== n5' |
    perl -lne 'print $& while / n[0-9]=*(?=\W) | \bn[0-9]\b /xg'
n1
n2===
n3
n4==
n5

그러나 이것이 당신이 원하는 것인지 확실하지 않습니다. 대신 이면 n2===x출력 n2===은 가 됩니다 n2==. 왜냐하면 마지막 항목이 ="비단어 문자로 끝남" 절을 충족하는 데 사용되기 때문입니다. (또는 오히려 "뒤에", 그렇지 않으면 for에 대한 일치도 n1=1가 됩니다 n1=. 즉 n1, 0 다음에 0 =이 오고 그 뒤에 단어가 아닌 문자가 옵니다 =.)

=*+기호 반환을 피하기 위해 소유 한정자를 사용할 수 있다고 생각합니다 =.

$ printf '%s\n' 'n1=1 n2===X n3=3 n4== n5' |
    perl -lne 'print $& while / n[0-9]=*+(?=\W) | \bn[0-9]\b /xg'
n1
n2
n3
n4==
n5

어쨌든, 당신이 원하는 것이 간단한 논리로 더 잘 달성될 수 있는지 궁금합니다. 즉, 문자열을 공백으로 분할하고, 하위 문자열을 기호로 분할하고 =, 개별 값을 살펴보세요.

관련 정보