繁体   English   中英

正则表达式捕获不带空格的PHP中的重复组

[英]Regex capturing repeating group in php without whitespace

我正在尝试通过PHP中的正则表达式解析字符串,该字符串始终具有以下格式: FooBar(,[0-9]{7}[0-9A-F]{8})+或换句话说,它们都有一个开始值/单词,后跟1个或多个条目,每个条目是一个逗号( , ),后跟7位数字和8个十六进制字符(数字或大写字母A至F)。

我的正则表达式捕获的是/^C7(,[0-9]{7}[0-9A-F]{8})+$/这类作品。 preg_match_all使用时,它返回一个包含两个条目的数组,第一个按预期输入字符串,但是,在第二个数组中只有一个条目,即最后一个匹配的块。 (请参见示例)

我需要捕获与捕获组匹配的所有块。 我进行了一些研究,发现了这个答案,该答案可能是相同的问题: https : //stackoverflow.com/a/2205009/2989952 ,所以我将正则表达式调整为/(,[0-9]{7}[0-9A-F]{8})+$/ ,但我仍然只有一场比赛。 可以在regex101.com上进行测试。 然后,我进行了更多的实验,发现,如果我更改输入字符串,以在块之间包含一个空格(或任何与此不匹配的字符),如下所示: C7,22801422CFE0F63 ,2280141C5EF0F63 ,22801402EFD0F63 ,2280138C5ED0F63 ,228024329897530 ,228023829877530并再次将正则表达式调整为/(,[0-9]{7}[0-9A-F]{8})+/它的功能与预期完全相同!

问题 :有没有一种方法可以实现此目的,使其与该循环组中的所有块都匹配而不在其之间添加空格? 如果是这样,怎么办?

编辑

为了说明问题:
没有空格 没有空格 https://regex101.com/r/ilkZjD/1

在此处输入图片说明 空格/随机字符 https://regex101.com/r/mimBgz/1

目标 :第二个空格的行为,一个空格,但不添加空格(分别是不匹配的字符)。

编辑2(hacky解决方案)

考虑到这个https://stackoverflow.com/a/3513858/2989952答案,我有点找到了解决方案。 正则表达式/(?:,)([0-9]{7}[0-9A-F]{8})/对我/(?:,)([0-9]{7}[0-9A-F]{8})/ https://regex101.com/r/LEEFzv/1。不过,我仍然想一种方法来匹配初始的FooBar 因为这表明传入的字符串应与此正则表达式完全匹配。
(我知道我可以为此简单地在第二个正则表达式中检查字符串,但是我很想在一个正则表达式中包含它)

范例
输入: 'C7,22801422CFE0F63,2280141C5EF0F63,22801402EFD0F63,2280138C5ED0F63,228024329897530,228023829877530'

那是你要的吗?

$in = 'C7,22801422CFE0F63 ,2280141C5EF0F63 ,22801402EFD0F63 ,2280138C5ED0F63 ,228024329897530 ,228023829877530';

preg_match_all('/(^\w+|\G)\h*(,[0-9]{7}[0-9A-F]{8})/', $in, $m);
print_r($m);

输出:

Array
(
    [0] => Array
        (
            [0] => C7,22801422CFE0F63
            [1] =>  ,2280141C5EF0F63
            [2] =>  ,22801402EFD0F63
            [3] =>  ,2280138C5ED0F63
            [4] =>  ,228024329897530
            [5] =>  ,228023829877530
        )

    [1] => Array
        (
            [0] => C7
            [1] => 
            [2] => 
            [3] => 
            [4] => 
            [5] => 
        )

    [2] => Array
        (
            [0] => ,22801422CFE0F63
            [1] => ,2280141C5EF0F63
            [2] => ,22801402EFD0F63
            [3] => ,2280138C5ED0F63
            [4] => ,228024329897530
            [5] => ,228023829877530
        )

)

说明:

(               : start group 1
  ^\w+          : beginning of line, 1 or more word characters
  |             : O
  \G            : match form this point
)               : end group 1
\h*             : 0 or more horizontal spaces
(               : start group 2
  ,             : a comma
  [0-9]{7}      : 7 digits
  [0-9A-F]{8}   : 8 hexa
)               : end group 2

要捕获包括第一部分在内的所有卡盘,您可以尝试:

(?:FooBar|(?:[0-9]{7}[0-9A-F]{8})+)

说明

  • 非捕获组(?:
  • 匹配FooBar
  • |
  • 您在一个捕获组中进行了一次或多次格式化(?:[0-9]{7}[0-9A-F]{8})+
  • 关闭非捕获组

    产量

嗯...也许我听不懂这个问题,但是您的正则表达式可以在第一种情况下删除尾随+

(,[0-9]{7}[0-9A-F]{8})

您可以使用A标志(即Anchored )构建模式以获取连续的匹配项。 主要的兴趣是您可以提取值并使用超前检查同时检查行的格式:

$pattern = '~
    (?!^)  # fails at the start of the string
    ( \h*,\h* (?<value>[0-9]{7}[A-F0-9]{8}) )
    # the first capture group is useful to shorten the 
    # the lookahead in the second branch.
  |
    (?<first>[a-zA-Z0-9]+)(?=(?1)*$)
~xA';

if ( preg_match_all($pattern, $yourstring, $matches) ) {
    echo $matches['first'][0], PHP_EOL;
    print_r(array_values(array_filter($matches['value'])));
} 

演示

A标志强制每个匹配项从字符串的开头或上一个匹配项的结尾开始。

第一个分支描述了逗号分隔的值,第二个分支描述了行的开头。

前瞻(?=(?1)*$)检查行的结构。 如果失败,则不可能匹配。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM