Grep 정규식 결과가 예상과 다른가요?

Grep 정규식 결과가 예상과 다른가요?

FreeBSD 11.1 사용:

#!/bin/sh

if printf 'abcde.fgh' | grep -iEq '^[^][$^*_-]'; then
    echo "test 1 success"
else
    echo "test 1 fail"
fi

echo

if printf 'abcde.fgh' | grep -iEq '^[^][.$^*_-]'; then
    echo "test 2 success"
else
    echo "test 2 fail"
fi

산출:

test 1 success

grep: Unmatched [ or [^
test 2 fail

그러나 AFAICT는 동일한 결과를 제공해야 합니다. 두 가지 모두 첫 번째 문자에만 해당 문자가 지정된 알파벳이 아닌 문자 목록 중 하나가 아니라는 조건이 포함되어 있습니다. 정규식 분석:

  • ^= 문자열의 시작
  • [^...]= 이러한 문자가 없으면 일치합니다.
  • 목록 내에서 ]첫 번째 문자여야 하고, ^첫 번째 문자가 아니어야 하며, -가 마지막 문자여야 합니다. ][.^$_-유효한 리터럴 문자 목록도 마찬가지 이며 문자열은 이들 중 어느 것과도 일치해서는 안 됩니다.
  • 혼란을 피하기 위해 이는 목록에 ][리터럴 "]"과 문자가 있음을 의미합니다."["~ 아니다목록 2개를 닫았다가 다시 엽니다.

2개의 표현식 사이의 유일한 차이점은 "."목록 내에 있다는 점입니다. 따라서 이는 다음과 같이 처리되어야 하며 not literal .실제로 첫 번째 문자는 리터럴과 일치하지 않습니다."."

내가 무엇을 놓치고 있나요? 아주 분명하고 간단한 것이겠죠?

답변1

몇 가지 다른 구문 규칙이 누락되었습니다. 대괄호 확장 내에는 일반 범위 외에도 로 시작하는 몇 가지 유형의 다중 문자 표현식도 있습니다 [. (참조정규식(7)매뉴얼리눅스또는FreeBSD"이것을 제외하고는그리고 '['를 사용하는 일부 조합(다음 단락 참조)".) 이는 다음과 같습니다.

  • 요소 대조: [..]
  • 동등한 클래스: [==]
  • 캐릭터 클래스: [::]

(다음과 같은 표현식을 보거나 사용했을 수 있습니다 . 이는 실제로 대괄호 확장 의 유일한 요소인 [[:digit:]]문자 클래스입니다 .)[:digit:][…]

따라서 귀하의 경우 는 .a 바로 뒤에 있으므로 [조합 요소의 여는 구분 기호로 인식됩니다. GNU grep 3.1에는 올바른 오류 메시지가 있습니다.

$ printf 'abcde.fgh' | grep -iEq '^[^][.$^*_-]'
grep: Unmatched [, [^, [:, [., or [=

[...]예를 들어 또는 [=.=]일반 점을 포함하거나 [=-=]이동할 곳이 없는 경우 대시와 일치시키기 위해 유사한 표현을 사용하여 이러한 상황을 탈출하는 데 사용할 수 있습니다 .

관련 정보