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의 일종의 버그입니까?
아이디어는 다음과 일치하는 것입니다.
n[0-9]
단어가 아닌 문자가 앞뒤에 옵니다.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
어쨌든, 당신이 원하는 것이 간단한 논리로 더 잘 달성될 수 있는지 궁금합니다. 즉, 문자열을 공백으로 분할하고, 하위 문자열을 기호로 분할하고 =
, 개별 값을 살펴보세요.