预匹配子模式不匹配

时间:2015-08-03 10:20:51

标签: php regex

我正在尝试验证增值税号码,我找到了以下模式:

 $pattern = '/^(
                        (AT)?U[0-9]{8} |                              # Austria
                        (BE)?0[0-9]{9} |                              # Belgium
                        (BG)?[0-9]{9,10} |                            # Bulgaria
                        (CY)?[0-9]{8}L |                              # Cyprus
                        (CZ)?[0-9]{8,10} |                            # Czech Republic
                        (DE)?[0-9]{9} |                               # Germany
                        (DK)?[0-9]{8} |                               # Denmark
                        (EE)?[0-9]{9} |                               # Estonia
                        (EL|GR)?[0-9]{9} |                            # Greece
                        (ES)?[0-9A-Z][0-9]{7}[0-9A-Z] |               # Spain
                        (FI)?[0-9]{8} |                               # Finland
                        (FR)?[0-9A-Z]{2}[0-9]{9} |                    # France
                        (GB)?([0-9]{9}([0-9]{3})?|[A-Z]{2}[0-9]{3}) | # United Kingdom
                        (HU)?[0-9]{8} |                               # Hungary
                        (IE)?[0-9]S[0-9]{5}L |                        # Ireland
                        (IT)?[0-9]{11} |                              # Italy
                        (LT)?([0-9]{9}|[0-9]{12}) |                   # Lithuania
                        (LU)?[0-9]{8} |                               # Luxembourg
                        (LV)?[0-9]{11} |                              # Latvia
                        (MT)?[0-9]{8} |                               # Malta
                        (NL)?[0-9]{9}B[0-9]{2} |                      # Netherlands
                        (PL)?[0-9]{10} |                              # Poland
                        (PT)?[0-9]{9} |                               # Portugal
                        (RO)?[0-9]{2,10} |                            # Romania
                        (SE)?[0-9]{12} |                              # Sweden
                        (SI)?[0-9]{8} |                               # Slovenia
                        (SK)?[0-9]{10}                                # Slovakia
                        )$/';


        $match = preg_match($pattern,$vat);

但是我似乎没有得到匹配。删除其余模式并删除外括号时,我确实得到了匹配。我已经不得不在开始和结束时添加正斜杠,因为它抱怨缺少结束分隔符。但我似乎无法让这个工作。有人能指出我正确的方向。

3 个答案:

答案 0 :(得分:1)

正则表达式模式是VERBOSE,因此您需要添加x modifier

  

x(PCRE_EXTENDED)
  如果设置了此修饰符,则模式中的空白数据字符将被完全忽略,除非转义或在字符类中,并且字符类外的未转义#字符与下一个换行符(包括在内)之间的字符也将被忽略。这相当于Perl的/x修饰符,并且可以在复杂模式中包含注释。但请注意,这仅适用于数据字符。空格字符可能永远不会出现在模式中的特殊字符序列中,例如在引入条件子模式的序列(?(中。

请参阅IDEONE demo

答案 1 :(得分:1)

你的正则表达式中需要x(扩展)修饰符。使用x可以在忽略模式中的#后使用空格和文本。

答案 2 :(得分:0)

如果将国家/地区模式提取到数组中的单独行(country - > pattern),可能会更好。然后使用像implode这样的字符串函数构造全局模式。你走了:

$vatPatterns = array(
    'Austria'        => '(AT)?U[0-9]{8}',
    'Belgium'        => '(BE)?0[0-9]{9}',
    'Bulgaria'       => '(BG)?[0-9]{9,10}',
    'Cyprus'         => '(CY)?[0-9]{8}L',
    'Czech Republic' => '(CZ)?[0-9]{8,10}',
    'Germany'        => '(DE)?[0-9]{9}',
    'Denmark'        => '(DK)?[0-9]{8}',
    'Estonia'        => '(EE)?[0-9]{9}',
    'Greece'         => '(EL|GR)?[0-9]{9}',
    'Spain'          => '(ES)?[0-9A-Z][0-9]{7}[0-9A-Z]',
    'Finland'        => '(FI)?[0-9]{8}',
    'France'         => '(FR)?[0-9A-Z]{2}[0-9]{9}',
    'United Kingdom' => '(GB)?([0-9]{9}([0-9]{3})?|[A-Z]{2}[0-9]{3})',
    'Hungary'        => '(HU)?[0-9]{8}',
    'Ireland'        => '(IE)?[0-9]S[0-9]{5}L',
    'Italy'          => '(IT)?[0-9]{11}',
    'Lithuania'      => '(LT)?([0-9]{9}|[0-9]{12})',
    'Luxembourg'     => '(LU)?[0-9]{8}',
    'Latvia'         => '(LV)?[0-9]{11}',
    'Malta'          => '(MT)?[0-9]{8}',
    'Netherlands'    => '(NL)?[0-9]{9}B[0-9]{2}',
    'Poland'         => '(PL)?[0-9]{10}',
    'Portugal'       => '(PT)?[0-9]{9}',
    'Romania'        => '(RO)?[0-9]{2,10}',
    'Sweden'         => '(SE)?[0-9]{12}',
    'Slovenia'       => '(SI)?[0-9]{8}',
    'Slovakia'       => '(SK)?[0-9]{1}',
);

$vatGlobalPattern = '/^(' . implode('|', $vatPatterns) . ')$/';

var_dump($vatGlobalPattern);

$vatsToCheck = array(
    'ATU12345678',
    '0123456789',
    'ATU1234',
);

$vatsChecked = array_map(function ($vat) use ($vatGlobalPattern) {
    return preg_match($vatGlobalPattern, $vat) === 1;
}, $vatsToCheck);

var_dump($vatsChecked);