이것은 내 샘플 텍스트입니다. grep w
, 매우 잘 작동합니다 grep ^w
.grep '^[ ]w'
[user@linux ~]$ grep w text.txt
whitespace 0
whitespace 1
whitespace 2
[user@linux ~]$
[user@linux ~]$ grep ^w text.txt
whitespace 0
[user@linux ~]$
1개의 공간이 있습니다
[user@linux ~]$ grep '^[ ]w' text.txt
whitespace 1
[user@linux ~]$
공백이 2개 있지만 동일한 출력을 얻습니다.
[user@linux ~]$ grep '^[ ]w' text.txt
whitespace 1
[user@linux ~]$
~에 따르면https://regex101.com/는 ^[ ]{0,}
줄 시작 부분에서 공백을 찾는 올바른 구문입니다. 그러나 Linux의 GNU grep에서는 제대로 작동하지 않습니다. 오류가 발생합니다 Invalid regular expression
.
[user@linux ~]$ grep ^[ ]{0,}w text.txt
grep: Invalid regular expression
[user@linux ~]$
이것들은 전혀 아무것도 반환하지 않습니다
[user@linux ~]$ grep '^[ ]{0}w' text.txt
[user@linux ~]$ grep '^[ ]{1}w' text.txt
[user@linux ~]$ grep '^[ ]{2}w' text.txt
[user@linux ~]$ grep '^[ ]{0,}w' text.txt
[user@linux ~]$
질문: ^[ ]{0,}
GNU grep과 함께 사용할 수 있나요? 그렇다면 이전 문법에 어떤 문제가 있었나요?
답변1
여기에는 온갖 종류의 문제가 있습니다. 첫째, 표현식의 ^[ ]w
의미는 다음과 같습니다. 줄의 시작 부분을 찾은 다음 정확히 하나의 공백을 찾은 다음 하나를 찾습니다 w
. 그래서 실제로 꽤 잘 작동합니다. 하나 이상의 공백과 일치하도록 하려면 [ ]
문자 클래스에 한정자를 추가해야 합니다.
$ grep '^[ ]\+w' text.txt
whitespace 1
whitespace 2
+
"하나 이상"을 의미합니다 . 사용되는 기본 정규식 스타일은 grep
BRE(기본 정규 표현식)라고 하며 이 정규식 스타일에서는 +
이스케이프가 필요하므로 \+
위의 * . 또는 플래그를 전달하여 ERE(확장 정규 표현식)를 사용 -E
하거나 -P
플래그를 전달하여 PCRE(Perl 호환 정규 표현식)을 사용할 수 있습니다. 이러한 정규식 스타일을 사용하면 +
수량자 역할을 하기 위해 이스케이프할 필요가 없습니다 .
$ grep -P '^[ ]+w' text.txt
whitespace 1
whitespace 2
$ grep -E '^[ ]+w' text.txt
whitespace 1
whitespace 2
다음 문제이자 더 중요한 문제는 정규식을 인용하지 않는다는 것입니다. 정규 표현식이 전달되도록 하려면 따옴표가 필요합니다.grep
있는 그대로쉘에 의해 먼저 해석되지 않습니다. 그러나 인용하지 않았으므로 에 전달되기 전에 셸에 의해 확장됩니다 grep
. set -x
쉘이 수행 중인 작업을 인쇄하도록 하는 옵션을 사용하여 이를 확인할 수 있습니다 :
$ set -x
$ grep ^[ ]{0,}w text.txt
+ grep '^[' ']0w' ']w' text.txt
grep: Invalid regular expression
^[
첫째, 및 사이에 공백이 있기 때문에 ]
쉘은 이를 두 개의 별도 인수인 ^[
및 로 해석합니다 ]{0,}w
. 그러나 {}
버팀대 확장을 위해 쉘에서 사용됩니다. 예를 들어:
$ echo foo{a,b}
fooa foob
그러나 확장의 두 번째 부분이 비어 있으면 다음과 같은 결과가 나타납니다.
$ echo foo{a,}
fooa foo
따라서 확장은 다음 ]{0,}w
과 같습니다.
$ echo ]{0,}w
]0w ]w
결과적으로 set -x
위 출력에서 볼 수 있듯이 이 세 가지 매개변수는 실제로 다음으로 전달됩니다 grep
.
'^[' ']0w' ']w'
그러나 인용하는 경우 +
위와 같이 BRE를 사용할 때 이스케이프 처리해야 합니다.
$ grep '^[ ]\{2\}w' text.txt
whitespace 2
마지막 참고 사항: [ ]
정확히 똑같습니다 . 개별 문자에 대해 문자 클래스를 사용하는 것은 의미가 없습니다.
이 모든 것을 종합하여 줄 시작 부분에서 정확히 하나의 공백과 일치하려면 다음을 사용하십시오.
$ grep '^ w' text.txt
whitespace 1
하나 이상을 일치시키려면 다음을 사용하십시오.
$ grep '^ \+w' text.txt
whitespace 1
whitespace 2
또는:
$ grep -E '^ +w' text.txt
whitespace 1
whitespace 2
또는
$ grep -P '^ +w' text.txt
whitespace 1
whitespace 2
특정 숫자 범위(예: 공백 0, 1, 2개)와 일치시키려면 다음을 수행하세요.
$ grep '^ \{0,3\}w' text.txt
whitespace 0
whitespace 1
whitespace 2
또는
$ grep -P '^ {0,3}w' text.txt
whitespace 0
whitespace 1
whitespace 2
또는
$ grep -E '^ {0,3}w' text.txt
whitespace 0
whitespace 1
whitespace 2
특정 숫자와 일치시키려면 {}
위에 표시된 대로 숫자를 설정하거나 문자를 N번 반복하십시오.
$ grep '^ \{2\}w' text.txt
whitespace 2
$ grep '^ w' text.txt
whitespace 1
$ grep '^ w' text.txt
whitespace 2
그리고항상 정규식을 인용하세요!
* 실제로 POSIX BRE에서는 +
특별한 의미가 없지만 BRE의 GNU 구현은 grep
이스케이프되면 이를 인식합니다.
답변2
BRE에서는 욕심 많은 수량자 표현식에서 {0,}
원하는 정규식 일치를 달성하려면 중괄호를 이스케이프해야 하며 항상인용하다정규식 문자열. 따옴표가 없으면 셸은 제공된 인수에 자체 구문 분석 구문을 적용하려고 시도하며 대부분의 경우 인수는 정규식의 일부만 grep
표시되도록 토큰화됩니다 .^[
grep '^[ ]\{0,\}w' file
~에서정규식 참조: 수량자그리고 GNU BRE를 선택하세요
\{n,\}
n >= 0
이전 항목 중 하나 이상이 반복 됩니다n
. 욕심쟁이(Greedy)이므로 이전 항목이 n번만 일치할 때까지 가능한 한 많은 항목을 일치시킨 후 이전 항목이 덜 일치하는 순열을 시도합니다.
주석에서 지적했듯이 using 은 *
modifier 를 사용하는 것과 동일합니다 \{0,\}
.
답변3
올바른 명령:
사용grep -E '^[ ]{0,}' text.txt
-E, --extended-regexp PATTERN을 확장 정규식(ERE, 아래 참조)으로 해석합니다.
작동하지 않는 이유:
정규식 주위에 작은따옴표를 사용하지 마십시오. bash가 이를 열고 명령은 다음과 같습니다.
grep '^[' ] ]0 text.txt
정규식을 사용하여 grep '^['
파일 로 변환됩니다 ]
.]0
text.txt
^[
[
특수 문자에도 종료 문자가 필요하기 때문에 잘못되었습니다.]
-E 옵션이 필요한 이유:
{m,n}은 확장 정규 표현식입니다. 이를 사용하려면 grep에 -E 옵션이 필요합니다.