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