에서 정규 표현식에 위키 백과 문서 , 그것은 보인다 [[:digit:]]
= [0-9]
= \d
.
그들이 같지 않은 상황은 무엇입니까? 차이점은 무엇입니까?
몇 가지 연구를 한 후에는 대괄호 표현 [:expr:]
이 로케일에 따라 달라집니다.
에서 정규 표현식에 위키 백과 문서 , 그것은 보인다 [[:digit:]]
= [0-9]
= \d
.
그들이 같지 않은 상황은 무엇입니까? 차이점은 무엇입니까?
몇 가지 연구를 한 후에는 대괄호 표현 [:expr:]
이 로케일에 따라 달라집니다.
답변:
예, [[:digit:]]
~ [0-9]
~입니다 \d
(여기서 ~는 근사값을 나타냄).
대부분의 프로그래밍 언어 (지원되는 경우) \d
≡ [[:digit:]]
(동일).
는 \d
보다 일반적입니다 [[:digit:]]
(하지 POSIX에서하지만 GNU에있다 grep -P
).
예를 들어 UNICODE 에는 많은 숫자 가 있습니다 .
123456789 # Hindu-Arabic
아라비아 숫자
٠١٢٣٤٥٦٧٨٩ # ARABIC-INDIC
۰۱۲۳۴۵۶۷۸۹ # EXTENDED ARABIC-INDIC/PERSIAN
߀߁߂߃߄߅߆߇߈߉ # NKO DIGIT
०१२३४५६७८९ # DEVANAGARI
이는 모두 포함될 수있다 에 [[:digit:]]
나 \d
.
대신 [0-9]
일반적으로 ASCII 숫자 0123456789
입니다.
Perl, Java, Python, C [[:digit:]]
와 같은 많은 언어가 있습니다 \d
. 예를 들어,이 펄 코드는 위의 모든 숫자와 일치합니다 :
$ a='0123456789 ٠١٢٣٤٥٦٧٨٩ ۰۱۲۳۴۵۶۷۸۹ ߀߁߂߃߄߅߆߇߈߉ ०१२३४५६७८९'
$ echo "$a" | perl -C -pe 's/[^\d]//g;' ; echo
0123456789٠١٢٣٤٥٦٧٨٩۰۱۲۳۴۵۶۷۸۹߀߁߂߃߄߅߆߇߈߉०१२३४५६७८९
Numeric
및 의 유니 코드 속성이있는 모든 문자를 선택하는 것과 같습니다 digits
.
$ echo "$a" | perl -C -pe 's/[^\p{Nd}]//g;' ; echo
0123456789٠١٢٣٤٥٦٧٨٩۰۱۲۳۴۵۶۷۸۹߀߁߂߃߄߅߆߇߈߉०१२३४५६७८९
어떤 grep이 재생할 수 있는지 (특정 버전의 pcre는 Perl과 다른 내부의 숫자 코드 포인트 목록이있을 수 있음) :
$ echo "$a" | grep -oP '\p{Nd}+'
0123456789
٠١٢٣٤٥٦٧٨٩
۰۱۲۳۴۵۶۷۸۹
߀߁߂߃߄߅߆߇߈߉
०१२३४५६७८९
다음을 보려면 [0-9]로 변경하십시오.
$ echo "$a" | grep -o '[0-9]\+'
0123456789
특정 POSIX BRE 또는 ERE의 경우 :
은 \d
(하지 POSIX이 아니라 GNU에 지원되지 않습니다 grep -P
).
[[:digit:]]
POSIX는 숫자 문자 클래스에 대응하기 위해 요구되며, ISO C에서는 문자 0부터 9까지가 필요합니다. 그래서 단지 C에서 로케일 모든 [0-9]
, [0123456789]
, \d
와 [[:digit:]]
정확히 같은 의미한다. 는 [0123456789]
어떤 가능한 오해가 없습니다 [[:digit:]]
더 유틸리티에서 사용할 수 있으며 만 의미하는 것이 일반적이다 [0123456789]
. 이 \d
유틸리티는 일부 유틸리티에서 지원됩니다.
에 관해서는 [0-9]
, 범위 표현의 의미는 C 로케일에서 POSIX에 의해서만 정의됩니다. 다른 로케일에서는 다를 수 있습니다 (코드 포인트 순서 또는 데이터 정렬 순서 또는 다른 것).
일부 구현에서는 범위가 일반 ASCII 순서 (예 : ksh93)와 다른 것으로 이해 될 수 있습니다.
$ LC_ALL=en_US.utf8 ksh -c 'a="'"$a"'";echo "${a//[0-9]}"'
۹ ߀߁߂߃߄߅߆߇߈߉ ९
그리고 그것은 기다리고있는 버그의 확실한 원인입니다.
iswctype()
및 POSIX 유틸리티의 BRE / ERE / 와일드 카드에서 [0-9] 및 [[: digit :]]는 0123456789에서만 일치합니다. 그리고 그것은 표준의 다음 개정판에서 밝혀 질 것입니다
perl
의 \d
유니 코드 모드가 다른 스크립트의 십진수와 일치 한다는 것을 알지 못했습니다 . 고마워 PCRE를 사용하면 (*UCP)
GNU에서 grep -Po '(*UCP)\d'
또는 grep -Po '(*UCP)[[:digit:]]
유니 코드 속성을 기반으로하는 클래스를 참조하십시오 .
[:digit:]
구문은 사용자가 숫자로 간주하는 현지화를 사용하고 싶다는 제안에 동의합니다 . [:digit:]
실제로는 [0-9]
절대로 0123456789와 일치하고 싶고 절대 일치 ٠١٢٣٤٥٦٧٨٩
하지 않으며 10 진수와 일치하고 싶은 유스 케이스를 생각할 수 없기 때문에 실제로 사용 하지 않습니다. POSIX 유틸리티가있는 모든 스크립트에서. zsh ML에 대한 현재 토론[:blank:]
도 참조하십시오 . 그 캐릭터 클래스는 약간 혼란입니다.
이것은 숫자를 정의하는 방법에 따라 다릅니다. [0-9]
ASCII로만되는 경향이 있습니다 (또는 ASCII 또는 ASCII의 상위 집합이 아닌 다른 비트 표현 (EBCDIC)을 가진 ASCII와 동일한 10 자리). \d
반면에 일반 숫자 (이전 버전의 Perl 또는 /a
정규식 플래그를 사용 하는 최신 버전의 Perl ) 일 수도 있고 유니 코드 일치 일 수도 있고 \p{Digit}
그보다 더 큰 숫자 세트 [0-9]
이거나 /\d/a
일치 할 수도 있습니다.
$ perl -E 'say "match" if 42 =~ m/\d/'
match
$ perl -E 'say "match" if "\N{U+09EA}" =~ m/\d/'
match
$ perl -E 'say "match" if "\N{U+09EA}" =~ m/\d/a'
$ perl -E 'say "match" if "\N{U+09EA}" =~ m/[0-9]/'
$
perldoc perlrecharclass
자세한 내용을 보거나 문제가있는 언어의 설명서를 참조하여 언어가 어떻게 작동하는지 확인하십시오.
그러나 더 많은 것이 있습니다! 로케일은 또한 \d
일치 하는 내용이 다를 \d
수 있으므로 전체 유니 코드 세트보다 적은 자릿수를 일치시킬 수 있으며 (일반적으로) 포함 [0-9]
합니다. 이것은 isdigit(3)
( [0-9]
)와 isnumber(3)
( [0-9
와 로케일의 다른 것 )의 C 차이와 유사합니다 .
숫자가 아닌 경우에도 숫자 값을 얻기 위해 호출 할 수 있습니다 [0-9]
.
$ perl -MUnicode::UCD=num -E 'say num(4)'
4
$ perl -MUnicode::UCD=num -E 'say num("\N{U+09EA}")'
4
$
[0-9]
.
다른 의미 [0-9]
, [[:digit:]]
그리고 \d
다른 답변에 제시되어있다. 여기에 정규식 엔진 구현에 차이점을 추가하고 싶습니다.
[[:digit:]] \d
grep -E ✓ ×
grep -P ✓ ✓
sed ✓ ×
sed -E ✓ ×
그래서 [[:digit:]]
항상 작동합니다 , \d
따라 달라집니다. 그렙의 매뉴얼에서는 그 언급 한 것 [[:digit:]]
그냥 0-9
에 C
로케일.
PS1 : 더 알고 있다면 표를 확장하십시오.
PS2 : GNU grep 3.1 및 GNU 4.4가 테스트에 사용됩니다.
grep
및의 많은 버전이 있으며 sed
GNU 버전과 다른 버전의 차이가 가장 큽니다. 그것의 버전을 언급 한 경우 대답은 더 유용 할 수 있습니다 grep
그리고 sed
그것은을 의미합니다. 또는 그 문제의 원인은 해당 테이블의 출처입니다. 이 이미지로 그것을 필요로 아무것도 포함하지 않기 때문에 2) 그 테이블뿐만 아니라 텍스트로 복사 할 수 있습니다
re
모듈은 [[: digit :]]를 지원하지 않지만 라이브러리에 추가는 regex
그것을 지원 하므로 항상 작동 할 때 약간 낄낄 거립니다. 항상 posix 불만 상황에서 작동합니다.
이론적 차이점은 다른 답변에서 이미 잘 설명되었으므로 실제 차이점 을 설명하는 것으로 남아 있습니다 .
다음은 숫자 일치와 관련된 일반적인 사용 사례입니다.
일부 숫자를 크런치하려고 할 때 숫자 자체가 어색한 형식의 텍스트 파일로되어있는 경우가 종종 있습니다. 프로그램에서 사용하기 위해 추출하려고합니다. 숫자 형식 (파일을보고)과 현재 로케일 을 알 수 있으므로 작업이 완료 되는 한 양식을 사용하는 것이 좋습니다. \d
가장 적은 키 스트로크가 필요하므로 매우 일반적으로 사용됩니다.
신뢰할 수없는 사용자 입력이있을 수 있으며 (웹 양식 일 수도 있음) 놀라움이 없는지 확인해야합니다. 데이터베이스의 숫자 필드에 저장하거나 쉘 명령의 매개 변수로 사용하여 서버에서 실행할 수 있습니다. 이 경우 [0-9]
가장 제한적이고 예측 가능한 것이기 때문에 정말로 원합니다 .
"위험한"어떤 것에도 사용하지 않을 약간의 데이터가 있지만 그것이 숫자인지 아는 것이 좋습니다. 예를 들어 프로그램에서 사용자가 주소를 입력 할 수 있으며 입력에 집 번호가없는 경우 가능한 오타를 강조 표시하려고합니다. 이 경우 가능한 한 넓게 가고 싶을 [[:digit:]]
것입니다.
숫자 일치에 가장 일반적인 3 가지 사용 사례 인 것 같습니다. 중요한 것을 놓쳤다 고 생각되면 의견을 남겨주십시오.