2011-01-24 5 views
4

HI,정규식 문자 클래스 빼기

내가 http://interim.cabinetoffice.gov.uk/media/291370/bs7666-v2-0-xsd-PostCodeType.htm에서 패턴을 사용하여, 영국의 우편 번호와 일치하도록 노력하고있어

/^[A-Z]{1,2}[0-9R][0-9A-Z]? [0-9][A-Z-[CIKMOV]]{2}$/ 

내가 PHP에서 이것을 사용하고,하지만하지 않습니다 유효한 우편 번호 OL13 0EF과 일치하십시오. 그러나이 우편 번호는 문자 클래스 뺄셈 -[CIKMOV]을 제거하면 일치합니다.

PHP에서 문자 클래스 빼기를 잘못하고 있다는 인상을받습니다. 누구든지 내 실수를 바로 잡을 수 있다면 가장 감사 할 것입니다.

미리 도움을 주셔서 감사합니다.

로스

답변

7

대부분의 정규 표현식은 문자 클래스 빼기를 지원하지 않습니다. 대신에 당신은 look-ahead 어설 션을 사용할 수 있습니다 :

/^[A-Z]{1,2}[0-9R][0-9A-Z]? [0-9](?!.?[CIKMOV])[A-Z]{2}$/ 
+0

+1 깨끗한 접근 방식. – codaddict

+0

나는 이것이 "깨끗한"방법을 실제로 얻지 못합니다. 이것은 더 시원한 솔루션이지만 의심의 여지가 없지만 다른 솔루션보다 훨씬 더 비밀스런 방법입니다. – fresskoma

+0

이것은 순수한 문자 클래스 솔루션이 아니며 모호합니다. {2}을 1 년 후 {3}으로 변경 한 다음 디버그 해보십시오. – sln

4

PCRE는 char 클래스 빼기를 지원하지 않습니다.

그래서 당신은 CIKMOV 제외한 모든 대문자를 열거 할 수 있습니다 :

로 범위를 사용하여 단락 될 수
^[A-Z]{1,2}[0-9R][0-9A-Z]? [0-9][ABDEFGHJLNPQRSTUWXYZ]{2}$ 

: 나는 당신이 [ABD-HJLNP-UW-Z][A-Z-[CIKMOV]]를 교체해야 할 것 같아요

^[A-Z]{1,2}[0-9R][0-9A-Z]? [0-9][ABD-JLNP-UW-Z]{2}$ 
1

. 나는 PHP가 문자 클래스 빼기를 지원한다고 생각하지 않는다. 나의 대안은 "A, B, D를 H, J, L, N, P에서 U, W에서 Z"와 같이 읽습니다.

5

클래스 빼기가 지원되지 않으면, 빼기를 얻기 위해 네거티브 클래스를 사용할 수 있어야합니다.

몇 가지 예는, [^\D] = \d 있습니다 [^[:^alpha:]] = [a-zA-Z]

귀하의 문제가 [^a-z[:^alpha:]CIKMOV]

[^
a-z # not a-z
[:^alpha:] # not not A-Za-z
CIKMOV # not C,I,K,M,O,V
같은 문자 클래스 내부에 부정적인 POSIX 문자 클래스를 사용하여, 그런 식으로 해결 될 수있다 ]

편집 -이 역시 작동하고 쉽게 읽을 수 있습니다 : [^[:^alpha:][:lower:]CIKMOV]

[^
[:^alpha:] # A-Za-z
[:lower:] # not a-z
CIKMOV # not C,I,K,M,O,V
]

결과없이 AZ하는 문자 클래스 C, I, K, M, O, V
기본적으로 빼기.
'AB DEFGH J L N PQRSTU WXYZ'
'AB DEFGH J L N PQRSTU WXYZ'

:

use strict; 
use warnings; 

my $match = ''; 

    # ANYOF[^\[email protected][-\377!utf8::IsAlpha] 
for (0 .. 255) { 
    if (chr($_) =~ /^[^a-z[:^alpha:]CIKMOV]$/) { 
     $match .= chr($_); next; 
    } 
    $match .= ' '; 
} 
$match =~ s/^ +//; 
$match =~ s/ +$//; 
print "'$match'\n"; 
$match = ''; 

    # ANYOF[^\[email protected][-\377+utf8::IsDigit !utf8::IsWord] 
for (0 .. 255) { 
    if (chr($_) =~ /^[^a-z\d\W_CIKMOV]$/) { 
     $match .= chr($_); next; 
    } 
    $match .= ' '; 
} 
$match =~ s/^ +//; 
$match =~ s/ +$//; 
print "'$match'\n"; 

출력 테스트 ASCII 문자 0-255 AZ 마이너스 CIKMOV의 중단을 나타낸다 : 여기

은 (펄) 2 명 개의 다른 수준의 혼성의 테스트입니다
+0

이라는 우편 번호가 있어야합니다.이 경우 ASCII 입력이 필요합니다. – SilentGhost

+0

@SilentGhost 내부적으로는 perl은 모두 바이트 문자열이며, 나가기 위해 인코딩하고, 들어 오기 위해 디코딩합니다. 코드 포인트는 평소와 달리 정규 표현식이 아닙니다. – sln

+0

@ Silent, Yea 그 클래스가 미리 정해진 클래스의 범위에없고 빼기 클래스가 없다면 다른 대안이 필요합니다. 이것은 단지 그 범위에있게됩니다. – sln