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}$/
Run Code Online (Sandbox Code Playgroud)
我在PHP中使用它,但它与有效的邮政编码不匹配OL13 0EF.但是,当我删除-[CIKMOV]字符类减法时,此邮政编码确实匹配.
我得到的印象是我在PHP中做了字符减法错误.如果有人能纠正我的错误,我将非常感激.
在此先感谢您的帮助.
罗斯
大多数正则表达式都不支持字符类减法.相反,你可以使用先行断言:
/^[A-Z]{1,2}[0-9R][0-9A-Z]? [0-9](?!.?[CIKMOV])[A-Z]{2}$/
Run Code Online (Sandbox Code Playgroud)
PCRE 不支持 char 类减法。
所以你可以枚举除 之外的所有大写字母CIKMOV:
^[A-Z]{1,2}[0-9R][0-9A-Z]? [0-9][ABDEFGHJLNPQRSTUWXYZ]{2}$
Run Code Online (Sandbox Code Playgroud)
可以使用 range 来缩短:
^[A-Z]{1,2}[0-9R][0-9A-Z]? [0-9][ABD-JLNP-UW-Z]{2}$
Run Code Online (Sandbox Code Playgroud)
小智 5
如果不支持类减法,则应该能够使用负类来实现减法.
一些例子是[^\D] = \d,[^[:^alpha:]] = [a-zA-Z]
您的问题可以像这样解决,在字符类中使用负POSIX字符类 [^a-z[:^alpha:]CIKMOV]
[^
a-z # not a-z
[:^alpha:] # not not A-Za-z
CIKMOV # not C,I,K,M,O,V
]
编辑 - 这也有效,可能更容易阅读:[^[:^alpha:][:lower:]CIKMOV]
[^
[:^alpha:] # A-Za-z
[:lower:] # not a-z
CIKMOV # not C,I,K,M,O,V
]
结果是一个没有C的字符类,I,K,M,O,V
基本上是一个减法.
这是对2种不同类混合的测试(在Perl中):
use strict;
use warnings;
my $match = '';
# ANYOF[^\0-@CIKMOV[-\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[^\0-@CIKMOV[-\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";
Run Code Online (Sandbox Code Playgroud)
输出显示AZ中的停止减去CIKMOV,来自测试的ascii字符0-255:
'AB DEFGH J L N PQRSTU WXYZ'
'AB DEFGH J L N PQRSTU WXYZ'