验证字符串仅包含限定字符和中间的特定可选子字符串

Validate string to contain only qualifying characters and a specific optional substring in the middle

我正在尝试在 PHP 中创建一个正则表达式。我可以用其他语言让它工作,但不能用 PHP.

我想验证数组中的项目名称

我当前的代码:

$regex = '/^[a-zA-Z0-9-_]+$/';    // contains A-Z a-z 0-9 - _
//$regex = '([^=>]$)';  // doesn't end with =>
//$regex = '~.=>~';  // doesn't start  with =>

if (preg_match($regex, 'Field_name_true2')) {
    echo 'true';
} else {
    echo 'false';
};
// Field=>Value-True
// =>False_name
//Bad_name_2=>

使用负面环视。开头负前瞻(?!=>)禁止以=>开头,结尾负后向(?<!=>)禁止以=>.

结尾
^(?!=>)(?:[a-zA-Z0-9-_]+(=>)?)+(?<!=>)$

DEMO

对于示例数据,您可以使用

^[a-zA-Z0-9_-]+=>[a-zA-Z0-9_-]+$

模式匹配:

  • ^ 字符串开头
  • [a-zA-Z0-9_-]+ 匹配任何列出的范围或字符 1+ 次(不能以 => 开头)
  • =>字面匹配
  • [a-zA-Z0-9_-]+ 再次匹配任何列出的范围或字符 1 次以上
  • $ 字符串结束

Regex demo

如果要允许可选空格:

^\h*[a-zA-Z0-9_-]+\h*=>\h*[a-zA-Z0-9_-]+\h*$

Regex demo

注意 [a-zA-Z0-9_-] 可以写成 [\w-]

嗯,你的字符范围等于 \w,所以你可以使用

^(?!=>)(?:(?!=>$)(?:[-\w]|=>))+$

这个构造使用了一个“tempered greedy token”,见a demo on regex101.com


更闪亮、更复杂并且肯定是最重要的,您可以使用子例程,如:

(?(DEFINE)
    (?<chars>[-\w])             # equals to A-Z, a-z, 0-9, _, -
    (?<af>=>)                   # "arrow function"
    (?<item>
        (?!(?&af))              # no af at the beginning
        (?:(?&af)?(?&chars)++)+
        (?!(?&af))              # no af at the end
    )
)
^(?&item)$

another demo on regex101.com

这里绝对不需要环顾四周。

锚和一个可选组就足够了。

Demo

/^[\w-]+(?:=>[\w-]+)?$/
        ^^^^^^^^^^^^^-- this whole non-capturing group is optional

这允许完全由 [0-9a-zA-Z-] 组成的完整字符串或由 =>.

拆分一次

非捕获组可能出现零次或一次。

换句话说,=> 可能出现在一个或多个 [\w-] 字符之后,但如果确实出现,则必须紧跟一个或多个 [\w-] 字符,直到字符串的结尾。


为了弥补问题要求中的一些歧义:

  • 如果 foo=>bar=>bam 有效,则使用 /^[\w-]+(?:=>[\w-]+)*$/?(零或一个)替换为 *(零或多个)。

  • 如果 foo=>=>bar 有效,则使用 /^[\w-]+(?:(?:=>)+[\w-]+)*$/=>(必须出现一次)替换为 (?:=>)+(子字符串必须出现一次或多次)次)。