PHP正则表达式用于URL字符串

6

示例字符串:

accuracy-is-5

accuracy-is-5-or-15

accuracy-is-5-or-15-or-20

package-is-dip-8-or-dip-4-or-dip-16

我的当前正则表达式:

/^([a-z0-9\-]+)\-is\-([a-z0-9\.\-]*[a-z0-9])(?:\-or\-([a-z0-9\.\-]*[a-z0-9]))*$/U

没有固定长度,部分:
\-or\-[a-z0-9\.\-]

可以重复。
现在从字符串“accuracy-is-5-or-15-or-20”中获得:
Array ( [0] => accuracy-is-5-or-15-or-20 [1] => accuracy [2] => 5 [3] => 20 )

15在哪里? :) 谢谢。


1
当捕获组重复时,最后一个值将覆盖之前的值。 - Casimir et Hippolyte
抱歉,我不理解vks下面的答案。 我该如何捕获我的示例中的所有值? - NMFES
2个回答

5
^\w+(?:-[a-zA-Z]+)+\K|\G(?!^)-(\d+)(?:(?:-[a-zA-Z]+)+|$)

你可以在这里使用\G来捕获所有组。每当一个捕获组被重复时,最后一个值会覆盖前一个值。请参见演示。https://regex101.com/r/tS1hW2/3

\G断言位置位于上一次匹配的末尾或字符串的开头(对于第一次匹配)。

编辑:

^\w+-is(?:-dip)?\K|\G(?!^)-(\d+)(?:-or(?:-dip)?|$)

如果您确定使用了 is,ordip,则可以使用此选项。请参见演示。

https://regex101.com/r/tS1hW2/4

$re = "/^\\w+-is(?:-dip)?\\K|\\G(?!^)-(\\d+)(?:-or(?:-dip)?|$)/m"; 
$str = "accuracy-is-5\naccuracy-is-5-or-15\naccuracy-is-5-or-15-or-20\npackage-is-dip-8-or-dip-4-or-dip-16"; 

preg_match_all($re, $str, $matches);

"package" - 这是一个属性名称。变量(例如大小,长度等)"-is-" - 字符串中始终存在(一次)"dip-8" - 它是属性的选项。变量(包装可能是dip-8、dip-4等。或黑色、白色...窗户、门)。"-or-" - 仅在属性选项超过一个时出现。 - NMFES
preg_match('/^\w+-is(?:-dip)?\K|\G(?!^)-(\d+)(?:-or(?:-dip)?|$)/m', 'accuracy-is-5-or-15-or-20', $matches); print_r($matches); 结果:Array ( [0] => ) - NMFES
在正则表达式中不应该出现"dip"。这是一个变量,选项名称。 "accuracy-is-5-or-15", "package-is-dip-8" .... "window-color-is-white-or-black" - NMFES
不行 :(
从字符串“package-is-dip-8-or-dip-4-or-dip-16”中,我需要获取一个包含子字符串的数组: “package”(它是属性名称),“dip-8”,“dip-4”,“dip-16”(它们是属性选项)。
- NMFES
这不正确。数组中只有数字(8、4、16)。我需要以“dip-8”、“dip-4”和“dip-16”的格式。并且没有属性名称(封装)。 - NMFES
显示剩余2条评论

3

当模式中的捕获组被重复使用时,以前的值将被最后一个值覆盖。因此,不能像这样使用 preg_match 设计您的模式。

一种可能的解决方案是使用 preg_match_all 查找模式的所有出现以及 \G 锚点,它是上一个匹配之后的位置。模式必须编写为一次只查找一个值。

\G 确保所有匹配都是连续的。为确保已到达字符串的末尾(换句话说,从开头到结尾正确格式化了字符串),一种便捷的方法是在末尾创建一个空的捕获组。因此,如果该捕获组出现在最后一次匹配中,则表示格式正确。

define('PARSE_SENTENCE_PATTERN', '~
(?:                                       # two possible beginings:
    \G(?!\A)                              # - immediatly after a previous match 
  |                                       # OR
    \A                                    # - at the start of the string
    (?<subject> \w+ (?>[-.]\w+)*? ) -is-  #  (in this case the subject is captured)
)
(?<value> \w+ (?>[-.]\w+)*? )  # capture the value
(?: -or- | \z (?<check>) )     # must be followed by "-or-" OR the end of the string \z
                               # (then the empty capture group "check" is created)
~x');

function parseSentence ($sentence) {

    if (preg_match_all(PARSE_SENTENCE_PATTERN, $sentence, $matches, PREG_SET_ORDER) &&
        isset(end($matches)['check']) ) 
        return [ 'subject' => $matches[0]['subject'],
                 'values'  => array_reduce ($matches, function($c, $v) {
                                  $c[] = $v['value']; return $c; }, $c = []) ];

    return false; // wrong format

}

// tests
$test_strings = ['accuracy-is-5', 'accuracy-is-5-or-15', 'accuracy-is-5-or-15-or-20',
                 'package-is-dip-8-or-dip-4-or-dip-16',
                 'bad-format', 'bad-format-is-', 'bad-format-is-5-or-'];

foreach ($test_strings as $test_string) {
    var_dump(parseSentence($test_string));
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接