2011-01-24 21 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

ほとんどの正規表現フレーバは、文字クラスの減算をサポートしていません。クラス減算がサポートされていません

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

+1クリーンなアプローチです。 – codaddict

+0

私はこれがどのように「クリーナー」なのか本当に分かりません。よりクーラーな解決策ですが、間違いなく、他のソリューションよりも隠された方法です。 – fresskoma

+0

これは純粋な文字クラスの解決策ではなく、あいまいです。今から{2}を{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
は基本的に減算です。ここ

は(Perlで)2つの異なるクラスの調合の試験である:
'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で中止を示します

+0

という郵便番号があるはずです。これにはアスキー入力が必要です。 – SilentGhost

+0

@SilentGhost内部的にはperlはすべてバイトストリングで、エンコードして出てくるようにデコードします。codepointsは普通のように、そうでなければ正規表現はありません。 – sln

+0

@ Silent、そうです。もしそれが所定のクラスの範囲になく、減算クラスがないなら、別の代替が必要です。これはちょうどその範囲にあるように起こります。 – sln

関連する問題