簡體   English   中英

用PHP進行正則表達式字符類減法

[英]Regex Character Class Subtraction with PHP

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中做了字符減法錯誤。 如果有人能糾正我的錯誤,我將非常感激。

在此先感謝您的幫助。

羅斯

大多數正則表達式都不支持字符類減法。 相反,你可以使用先行斷言:

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

如果不支持類減法,則應該能夠使用負類來實現減法。

一些例子是[^\\D] = \\d[^[:^alpha:]] = [a-zA-Z]

您的問題可以像這樣解決,在[^az[:^alpha:]CIKMOV]等字符類中使用負POSIX字符類

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

編輯 - 這也有效,可能更容易閱讀: [^[:^alpha:][:lower:]CIKMOV]

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

結果是一個字符類,它是沒有C,I,K,M,O,V的AZ
基本上是一個減法。

這是對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";

輸出顯示AZ中的停止減去CIKMOV,來自測試的ascii字符0-255:
'AB DEFGH JLN PQRSTU WXYZ'
'AB DEFGH JLN PQRSTU WXYZ'

PCRE不支持char類減法。

所以你可以枚舉除CIKMOV之外的所有大寫字母:

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

可以使用范圍縮短為:

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

我想你將不得不用[ABD-HJLNP-UW-Z]取代[AZ-[CIKMOV]] [ABD-HJLNP-UW-Z] 我不認為php支持字符類減法。 我的替代方案是“A,B,D到H,J,L,N,P到U,W到Z”。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM