preg_match 包含无限次出现的字符串

preg_match include string with unlimit occurence

我正在尝试创建 preg_match 具有模式的函数来验证未来字符串的出现次数不受限制。这是我的函数:

if(! preg_match_all("#^\([a-zA-Z0-9_-]+\)$#", $arg, $matches, PREG_OFFSET_CAPTURE)){
    var_dump($matches);
    throw new \Exception('The simple pattern "'.$arg.'" is not valid !');
}

出现一次必须遵守以下格式,两个括号之间的任何字符:(mystring123/)。 整个字符串 ($arg) 是这些事件的集合。
例如
1-此字符串有效 (AAA/)(BBB/)(cc).
2-此字符串无效 (AAA/)xxxx(BBB/)(cc)

该函数工作正常,但我尝试创建的模式不接受多次出现。

我第二次尝试,我改变了模式,但是在执行 preg_match 功能时触发了问题。

#[^\([a-zA-Z0-9_-]+\)$]+#

我需要的是如何解决这个问题,以及如何将后续字符“\”和“/”添加到模式字符串中。

\ 在字符转义之前的用法,因此将搜索它。如果您要查找 /,只需创建一个类似 \/ 的模式。如果您要查找 \,请试试这个:\。所以 \\/\.\/\ 会找到 \/./\。 通常,您的搜索模式以 php 中的 / 开始和结束。喜欢/[a-zA-Z]\./

要尝试一些新的正则表达式,请尝试此站点:https://regex101.com/

它会解释您输入的每个字符,还会显示它是否仅适用于一个或多个样本。

如果我没记错的话你的 $arg 可能是一个字符串 (AAA/)(BBB/)(cc) 有效,(AAA/)xxxx(BBB/)(cc) 无效。

如果是这种情况,并且您想在 character class 中匹配您接受的字符的出现,您可以将您的 字符和括号,然后将其作为非捕获组重复。

您当前的字符 class [a-zA-Z0-9_-] 不包含正斜杠,因此您可以添加正斜杠以匹配出现的 (AAA/)。您还可以添加反斜杠。 This page 对转义反斜杠有很好的解释。

您可以将正则表达式更新为:

^(?:\([/a-zA-Z0-9_\-]+\))+$

或使用\w匹配一个word character匹配[a-zA-Z0-9_]。这看起来像 [/\w\-]+

那会匹配

  • ^ 字符串的开头
  • (?:非捕获组
    • \( 匹配(
    • [/a-zA-Z0-9_\-]+您允许的字符在字符集中重复一次或多次
    • \)匹配)
  • )+关闭非捕获组并重复一次或多次
  • $字符串结束

您的代码可能如下所示:

if(! preg_match_all("#^(?:\([/a-zA-Z0-9_\\-]+\))+$#", $arg, $matches, PREG_OFFSET_CAPTURE)){
    var_dump($matches);
    throw new \Exception('The simple pattern "'.$arg.'" is not valid !');
}

Demo php

我已经为这项任务辛勤工作了一段时间,试图设计一种方法将您的全字符串验证与不确定的捕获组结合起来。在尝试了很多 \G 和 lookarounds 的组合后,恐怕无法一次完成。如果 php 允许可变宽度后视,我想我可以,但可惜它们不可用。

我能提供的是一个去除了不必要的“东西”的过程。

代码:(Demo)

$strings = ["(AAA/)(BBB/)(cc)", "(AAA/)xxxx(BBB/)(cc)"];

foreach ($strings as $string) {
    if (!preg_match('~^(?:\([\w\/-]+\))+$~', $string)) {
        echo "The simple pattern $string is not valid!";
        // throw new \Exception("The simple pattern $string is not valid!");
    } else {
        var_export(preg_split('~\)\K~', $string, 0, PREG_SPLIT_NO_EMPTY));
    }
    echo "\n";
}

输出:

array (
  0 => '(AAA/)',
  1 => '(BBB/)',
  2 => '(cc)',
)
The simple pattern (AAA/)xxxx(BBB/)(cc) is not valid!

模式 #1 细分:

~              #pattern delimiter
^              #start of string anchor
(?:            #start of non-capturing group
  \(           #match one opening parenthesis
  [\w\/-]+    #greedily match one or more of the following characters: a-z, A-Z, 0-9, underscores, backslashes, slashes, and hyphens
  \)           #match one closing parenthesis
)              #end of non-capturing group
+              #allow one or more occurrences of the non-capturing group
$              #end of string anchor
~              #pattern delimiter

模式 #2 细分:

~              #pattern delimiter
\)             #match one closing parenthesis
\K             #restart the fullstring match (forget/release previously matched character(s))
~              #pattern delimiter

模式 #2 的作用是定位每个右括号并在右括号后的零宽度位置“分解”字符串。 \K 确保没有角色在爆炸中伤亡。

if 条件不需要调用 preg_match_all(),因为在验证从 ^$ 时,只能有一个匹配的字符串。声明一个包含“匹配”的变量是没有意义的(就像 PREG_OFFSET_CAPTURE 一样)——如果有匹配,它将是整个输入字符串,所以如果需要就使用那个值。

preg_split()preg_match_all() 调用的合适替代品,因为它准确输出您将在精简 single-dimensional 数组中寻找的输出,并且使用非常小的可读模式。 *第3个和第4个参数:0PREG_SPLIT_NO_EMPTY分别告诉函数爆炸次数“没有限制”,任何空元素都应该被丢弃(不要做空) 中尾随 cc)

的元素