与给定模式匹配的正则表达式,以可选数字结尾

时间:2018-06-12 16:49:47

标签: php regex

我一直在尝试使用正则表达式来匹配和提取网址的各个部分。 URL模式如下所示:

http://domain.abcdef/xyz/fe/fi/fo5/fu2m/123/

我打算捕获以下群组:

  1. 匹配并捕获xyz(可选,但具体值)
  2. 匹配并捕获fe/fi/fo5/fu2m(必须存在,任意值)
  3. 匹配并捕获123(可选数字值,必须出现在最后)
  4. 以下是我尝试过的表达式和遇到的问题:

    string1:http://domain.abcdef/xyz/fe/fi/fo5/fu2m/123/

    string2:http://domain.abcdef/xyz/fe/fi/fo5/fu2m/

    ^(?:https?:\/\/)?(?:[\da-z\.-]+)\.(?:[a-z\.]{2,6})(?:\/(xyz))?\/([\/\w]+)+(?:\/([\d]+))\/$
    
    • 将号码设为必填

    • 匹配并捕获string1中所需的所有组,即使未包含xyz

    • 在string2中没有匹配,因为最后没有数字

       ^(?:https?:\/\/)?(?:[\da-z\.-]+)\.(?:[a-z\.]{2,6})(?:\/(xyz))?\/([\/\w]+)+(?:\/([\d]+))?\/$
      
    • 使数字在结尾处可选

    • 仅捕获string1和string2中的第1组和第2组。数字与字符串2中的第2组匹配为fe/fi/fo5/fu2m/123

    我的问题是如何在所有场景中捕获组1,2和3。 string1和string2(注意:我正在使用PHP' s preg_match函数)

2 个答案:

答案 0 :(得分:0)

我将首先使用parse_url从网址中提取路径。然后你要做的就是在第二组中使用非贪婪的量词:

$path = parse_url($url, PHP_URL_PATH);

if ( preg_match('~^\A/([^/]+)/(.*?)/(?:(\d+)/)?\z~', $path, $m) )
    var_dump($m);

这样,如果最后的数字丢失,非贪婪量词(来自第二组)将被强制到达字符串的末尾。

答案 1 :(得分:0)

使用修改后的网址验证程序。

'~^(?!mailto:)(?:(?:https?|ftp)://)?(?:\S+(?::\S*)?@)?(?:(?:(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z\u00a1-\uffff0-9]+-?)*[a-z\u00a1-\uffff0-9]+)(?:\.(?:[a-z\u00a1-\uffff0-9]+-?)*[a-z\u00a1-\uffff0-9]+)*(?:\.(?:[a-z\u00a1-\uffff]{2,})))|localhost)(?::\d{2,5})?(?:/(xyz))?((?:/(?!\d+/?$)[^/]*)+)(?:/(\d+))?/?\s*$~'

第1组是可选的xyz
第2组是中间的 第3组是最后的可选数字

可读版本

 ^ 
 (?! mailto: )
 (?:
      (?: https? | ftp )
      ://
 )?
 (?:
      \S+ 
      (?: : \S* )?
      @
 )?
 (?:
      (?:
           (?:
                [1-9] \d? 
             |  1 \d\d 
             |  2 [01] \d 
             |  22 [0-3] 
           )
           (?:
                \.
                (?: 1? \d{1,2} | 2 [0-4] \d | 25 [0-5] )
           ){2}
           (?:
                \.
                (?:
                     [1-9] \d? 
                  |  1 \d\d 
                  |  2 [0-4] \d 
                  |  25 [0-4] 
                )
           )
        |  (?:
                (?: [a-z\u00a1-\uffff0-9]+ -? )*
                [a-z\u00a1-\uffff0-9]+ 
           )
           (?:
                \.
                (?: [a-z\u00a1-\uffff0-9]+ -? )*
                [a-z\u00a1-\uffff0-9]+ 
           )*
           (?:
                \.
                (?: [a-z\u00a1-\uffff]{2,} )
           )
      )
   |  localhost
 )
 (?: : \d{2,5} )?
 (?:
      / 
      ( xyz )  # Optional specific value
 )?
 (  # Must exist, arbitrary value
      (?:
           /
           (?! \d+ /? $ )  # Not a numeric value at the end
           [^/]* 
      )+
 )
 (?:
      / 
      ( \d+ )  # Optional numeric value, which must appear at the end
 )?
 /?
 \s* 
 $   

输出

 **  Grp 0 -  ( pos 0 : len 46 ) 
http://domain.abcdef/xyz/fe/fi/fo5/fu2m/123/

 **  Grp 1 -  ( pos 21 : len 3 ) 
xyz  
 **  Grp 2 -  ( pos 24 : len 15 ) 
/fe/fi/fo5/fu2m  
 **  Grp 3 -  ( pos 40 : len 3 ) 
123  



 **  Grp 0 -  ( pos 48 : len 42 ) 
http://domain.abcdef/xyz/fe/fi/fo5/fu2m/

 **  Grp 1 -  ( pos 69 : len 3 ) 
xyz  
 **  Grp 2 -  ( pos 72 : len 18 ) 
/fe/fi/fo5/fu2m/

 **  Grp 3 -  NULL