正则表达式在 php 中捕获没有空格的重复组
Regex capturing repeating group in php without whitespace
我正在尝试通过 PHP 中的正则表达式解析始终具有以下格式的字符串:
FooBar(,[0-9]{7}[0-9A-F]{8})+
或换句话说,它们有一个开始 value/word 后跟 1 个或多个条目,每个条目是一个逗号 (,
),后跟 7 位数字和 8 个十六进制字符(数字或大写字符 A 到 F)。
我的 Regex 捕获这个是 /^C7(,[0-9]{7}[0-9A-F]{8})+$/
哪种作品。当在 preg_match_all
中使用时,它 returns 是一个包含两个条目的数组,第一个是预期的输入字符串,但是,在第二个数组中只有一个条目,即最后一个匹配的块。 (见示例)
我需要捕获捕获组匹配的所有块。我做了一些研究并找到了这个答案,它似乎是关于同一个问题:, So I've adjusted my regex to /(,[0-9]{7}[0-9A-F]{8})+$/
, but I still only get one match. This can be tested at regex101.com。然后我又做了一些实验,发现如果我更改输入字符串,在块之间包含一个 space(或任何不匹配的字符),如下所示:C7,22801422CFE0F63 ,2280141C5EF0F63 ,22801402EFD0F63 ,2280138C5ED0F63 ,228024329897530 ,228023829877530
并调整正则表达式再次 /(,[0-9]{7}[0-9A-F]{8})+/
它完全按照预期的方式执行!
问题:有没有办法做到这一点,匹配这个循环组中的所有块而不在中间添加白色space?如果是,怎么做?
编辑
说明问题:
无白spacehttps://regex101.com/r/ilkZjD/1
Whitespace/random 个字符 https://regex101.com/r/mimBgz/1
目标:第二个的行为,带有白色spaces,但不添加白色spaces(分别是不匹配的字符).
编辑 2(hacky 解决方案)
我找到了一个解决方案,考虑到这个 Answer. The Regex /(?:,)([0-9]{7}[0-9A-F]{8})/
works for me. 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})+
关闭非捕获组
您可以使用 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)*$)
向前检查行的结构。如果这个失败,则无法匹配。
ehmmm...也许我无法理解这个问题,但您的正则表达式将适用于第一种情况,删除尾随 +
(,[0-9]{7}[0-9A-F]{8})
我正在尝试通过 PHP 中的正则表达式解析始终具有以下格式的字符串:
FooBar(,[0-9]{7}[0-9A-F]{8})+
或换句话说,它们有一个开始 value/word 后跟 1 个或多个条目,每个条目是一个逗号 (,
),后跟 7 位数字和 8 个十六进制字符(数字或大写字符 A 到 F)。
我的 Regex 捕获这个是 /^C7(,[0-9]{7}[0-9A-F]{8})+$/
哪种作品。当在 preg_match_all
中使用时,它 returns 是一个包含两个条目的数组,第一个是预期的输入字符串,但是,在第二个数组中只有一个条目,即最后一个匹配的块。 (见示例)
我需要捕获捕获组匹配的所有块。我做了一些研究并找到了这个答案,它似乎是关于同一个问题:, So I've adjusted my regex to /(,[0-9]{7}[0-9A-F]{8})+$/
, but I still only get one match. This can be tested at regex101.com。然后我又做了一些实验,发现如果我更改输入字符串,在块之间包含一个 space(或任何不匹配的字符),如下所示:C7,22801422CFE0F63 ,2280141C5EF0F63 ,22801402EFD0F63 ,2280138C5ED0F63 ,228024329897530 ,228023829877530
并调整正则表达式再次 /(,[0-9]{7}[0-9A-F]{8})+/
它完全按照预期的方式执行!
问题:有没有办法做到这一点,匹配这个循环组中的所有块而不在中间添加白色space?如果是,怎么做?
编辑
说明问题:
目标:第二个的行为,带有白色spaces,但不添加白色spaces(分别是不匹配的字符).
编辑 2(hacky 解决方案)
我找到了一个解决方案,考虑到这个 Answer. The Regex /(?:,)([0-9]{7}[0-9A-F]{8})/
works for me. 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})+
关闭非捕获组
您可以使用 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)*$)
向前检查行的结构。如果这个失败,则无法匹配。
ehmmm...也许我无法理解这个问题,但您的正则表达式将适用于第一种情况,删除尾随 +
(,[0-9]{7}[0-9A-F]{8})