GNU grep에서 \< 및 \> 정규식 기호의 의미

GNU grep에서 \< 및 \> 정규식 기호의 의미

다음 정규식 예는 "정규식 마스터하기"의 22페이지에서 가져온 것입니다.

'\<([a-z]+) +\1\>'

저는 정규식을 처음 접했지만 책에서 이를 명시적으로 언급하지는 않았지만 표준 정규식 기호가 아니라는 인상을 \<받았습니다 \>. 검색해 보면 grep정규식 구문에 대한 GNU 확장 인 것으로 보입니다 . 어쩌면 구체적이지 않을 수도 있습니다 grep. 확실하지 않습니다.

어떤 경우 에라도,이 기호가 무엇을 의미하는지 잘 모르겠습니다.. 이 질문의 나머지 부분에서는 다른 정의 또는 정의 시도를 인용합니다. 그 중 일부는 분명히 틀렸거나, 이해할 수 없거나, 적어도 불완전합니다. 누군가 나에게 정확한 정의를 알려줄 수 있다면 감사하겠습니다. 마지막 인용문은 다음과 같습니다.https://www.grymoire.com/Unix/Regular.html#uh-9, 정답일 가능성이 높습니다. 그러나 공식 문서에는 다르게 나와 있습니다.

책은 말한다

(이상해 보일 수도 있는) 메타 시퀀스 \<\>[...]을 사용할 수 있습니다. ^각각 $단어의 시작과 끝 위치를 일치시키는 및 의 단어 기반 버전으로 생각할 수 있습니다 .

그럼 나중에

"단어의 시작"은 단순히 일련의 영숫자 문자가 시작되는 위치입니다. "단어의 끝"은 이러한 시퀀스가 ​​끝나는 위치입니다. 다음 페이지의 그림 1-2에서는 이러한 위치가 표시된 예제 라인을 보여줍니다.

그림 1-2가 도움이 됩니다.

에도 "기록"되어 있습니다.GNU findutils 매뉴얼 이는 다음과 같이 말합니다.

‘\<’ matches the beginning of a word
‘\>’ matches the end of a word

거기에도GNU grep 매뉴얼그것은 말한다:

'\<'
    Match the empty string at the beginning of word.
'\>'
    Match the empty string at the end of word.

이 설명이 무엇을 의미하는지 모르겠습니다. 그러므로 GNU 매뉴얼에서 발췌한 내용 중 어느 것도 도움이 되지 않습니다.

처음에 이 질문을 썼을 때 "정규식 익히기" 섹션을 주의 깊게 읽지 않았고 그림 1-2도 보지 않았으며 해당 기호가 "단어 I" 앞이나 뒤에 공백 문자가 있다는 뜻이라고 생각했습니다. 이제 이것이 틀렸다는 것을 깨달으십시오. 그러나 책의 설명조차도 부정확하거나 불완전합니다.

다음 두 가지 예를 고려하십시오.

grep --color -E -i '\<([a-z]+) +\1\>' <<< 'wibble someword someword-something else wibble'

이는 "someword someword"와 일치합니다.

grep --color -E -i '\<([a-z]+) +\1\>' <<< 'wibble someword someword_something else wibble'

여기에는 일치하는 항목이 없습니다.

이 책에서는 "단어 끝"이 영숫자 시퀀스가 ​​끝나는 곳이라고 말하기 때문에 이것을 설명하지 않습니다. GNU 매뉴얼에서 발췌한 내용도 마찬가지입니다.

가능한 설명은 다음에서 제공됩니다.https://www.grymoire.com/Unix/Regular.html#uh-9(무작위 검색으로 찾았습니다) 내용은 다음과 같습니다.

단어 검색은 언뜻 보이는 것만큼 간단하지 않습니다. 문자열 "the"는 "other"라는 단어와 일치합니다. 문자 앞뒤에 공백을 추가하고 " the "라는 정규식을 사용할 수 있습니다. 그러나 이는 줄의 시작이나 끝 부분에 있는 단어와 일치하지 않습니다. 그리고 단어 뒤에 구두점이 있는 경우에는 일치하지 않습니다.

"t" 앞의 문자는 개행 문자이거나 문자, 숫자, 밑줄 이외의 문자여야 합니다. "e" 다음의 문자는 숫자, 문자, 밑줄 이외의 문자여야 하며 줄 종결자일 수도 있습니다.

저자가 여기에서 이것을 얻고 있는지는 모르겠지만 그것이 사실이라고 가정하면 내가 보고 있는 동작을 설명할 수 있습니다. 하지만 여전히 꽤 캐주얼해 보입니다. -구두점이 아닙니다. 왜 단어의 일부로 포함될 수 없나요? 또는 다르게 말하면 하이픈은 단어의 끝과 일치하지만 밑줄은 일치하지 않는 이유는 무엇입니까? 실제로 자연어에서는 밑줄보다 하이픈이 더 일반적입니다. 프로그래밍 언어에서는 밑줄을 사용할 수 있습니다.

이것이 맞다면 GNU 문서는 실제로 이를 정확하게 문서화해야 합니다. 이 내용을 이해했다면 버그 보고서를 제출할 수 있나요?

이상적으로는 이 기능을 사용자 정의할 수 있습니다. 하지만 어쩌면 그것은 너무 많은 것을 요구할 수도 있습니다.

GNU 코드에서 발췌한 이 grep내용은www.grymoire.com맞을 수도 있습니다. 관련 코드는 init_word_char"lib/regcomp.c"의 함수에 있으며 다음과 같습니다.

general_case:
  for (; i < BITSET_WORDS; ++i)
    for (j = 0; j < BITSET_WORD_BITS; ++j, ++ch)
      if (isalnum (ch) || ch == '_')
        dfa->word_char[i] |= (bitset_word_t) 1 << j;

여기서 중요한 줄은 물론 파일의 983번 줄입니다.

if (isalnum (ch) || ch == '_')

즉, 문자는 영숫자 또는 밑줄입니다.

물론 저는 이 코드가 무엇을 의미하는지 잘 이해하지 못합니다.

답변1

정규식과 관련된 "단어"에 대한 공식적이고 정확한 정의를 가정하는 것처럼 보이지만 의미는 실제로 구현에 따라 다릅니다.

실제로 인용한 책의 "정규식 명명법", "맛" 단락에서

두 프로그램이 ⌈\<···\>⌋를 지원하더라도 자신이 수행하는 작업에 동의하지 않고 이를 단어로 간주하지 않을 수 있습니다."

이 개념의 가변성을 보여주는 예로서,Wikipedia의 정규식 페이지[:word:][:word:]밑줄을 포함하지만 기호와 연결된 각주를 포함하도록 비표준 문자 클래스를 정의합니다.Emacs Lisp 매뉴얼여기서 문자 클래스는 "단어 구문이 있는 모든 문자"와 일치한다고 하며, 추가로 연결됩니다.구문 클래스 테이블저것아니요"단어 구성 요소"에 밑줄을 나열합니다("기호 구성 요소"에 나열 - "변수 및 명령 이름과 단어 구성 요소에 사용되는 추가 문자"로 정의됨).

이런 관점에서 볼 때, 위의 진술은 명백히 부정확합니다.

"단어의 시작"은 단순히 일련의 영숫자가 시작되는 곳입니다."

정의보다는 단순화로 볼 수 있습니다.

"단어 시작 부분과 일치" 및 "단어 시작 부분의 위치 일치"와 같은 표현도 그다지 형식적으로 들리지 않습니다. 빈 문자열을 포함하는 버전은 덜 명확하지만 더 정확합니다.공식적으로 정의된 개념1 .

거의,

'\<'는
    단어 시작 부분의 빈 문자열과 일치합니다.

\<문자열 에 단어 형성 문자( GNU grep 정의에 따른 [:alnum:]문자 클래스의 하나 또는 a _)가 포함되어 있고 단어 형성 문자 바로 앞에 있지 않은 경우에만 문자열이 일치함 을 나타냅니다 .

그러면 예제의 패턴은 \<([a-z]+) +\1\>"하나 이상의 소문자 알파벳 문자 시퀀스(로케일에서 "a"와 "z" 사이로 정렬됨)로 읽힐 수 있습니다. 여기서 첫 번째 문자 바로 앞에는 단어 만들기 문자가 없고 그 뒤에는 하나 이상의 공백으로 시작하고 그 앞에 전체 소문자 알파벳 문자가 오고 마지막 문자 뒤에 단어 만들기 문자가 없습니다.


1 정규식 컨텍스트에서 길이가 0인 문자열입니다. 맞을 수도 있겠네요, 정말모든줄에는 빈 줄을 포함하여 해당 항목이 포함됩니다. ~이 되다연결 작업의 ID 요소, 리터럴 문자 앞이나 뒤에 일치할 수 있습니다. 예를 들어, X*에서 일치하는 것, 에서 일치하는 빈 패턴 grep 'oX*o' <<<foo, 에서 일치하는 것, ;에서 일치하는 것입니다.''grep '' <<<''echo "" | grep '^$'\<grep '\<' <<<'a'

답변2

그 부분GNU grep 매뉴얼에서설명하다:

\<단어 시작 부분의 빈 문자열과 일치합니다.

\>단어 끝의 빈 문자열과 일치합니다.

"단어"의 시작과 끝과 일치하므로 \<barstring 과 foo bar일치하거나 단지 일치 bar하지만 string 과는 일치하지 않습니다 foobar. 일치는 빈 ​​문자열과 일치하는 것으로 설명됩니다. 왜냐하면 일치할 때 \<bar일치 foo barbareg 가 아니라 단지 <space>bar이며 \<일치하는 문자열( eg 와 관련됨 grep -o)에 문자가 추가되지 않기 때문입니다.

표준이 아닙니다.

\w의 동의어인 단어 구성 요소를 일치시킵니다 [_[:alnum:]].

매뉴얼에는 다음과 같은 내용이 나와 있습니다. 작은 글씨에 주의하세요. 단어 문자에는 영숫자(현재 로케일에서 의미하는 모든 것)가 포함됩니다.밑줄을 긋고. 따라서 두 번째 시도에서 찾고 있는 내용과 실제로 일치하지 않습니다 someword_something.someword\>grep

예, 이는 많은 프로그래밍 언어에서 식별자 이름에 영숫자와 밑줄이 허용되기 때문입니다. 하이픈은 아니고 빼기 연산자입니다.

물론 C와 Javascript에서는 $식별자 이름에도 유효하며 식별자 이름은 숫자로 시작할 수 없지만 모든 것을 가질 수는 없습니다.

관련 정보