为 Unicode 正则表达式中的特定字符 class 部分设置长度限制

Set length limits to specific character class parts in Unicode regular expression

下面我的正则表达式:

preg_match('/^[\p{L}\p{N} @]+$/u', $string);

我的目标是设置 \p{L}\p{N}@ 和整个字符串的最小和最大长度。我尝试将 {min, max} 放在 \p{L} 之后和每个部分之后,但它不起作用。

您可以在需要重复的子模式之后借助限制量词设置模式的最小和最大长度。

这里我们需要使用一个技巧来确保我们可以计算不连续的子模式。它可以用否定字符 类 和开头的前瞻来完成。

这是*至少 4 个字母 \p{L}、至少 5 和 6 个最大数字 \p{N} 以及至少三个 @:[=24 的正则表达式示例=]

^(?=(?:[^\n\p{L}]*\p{L}){4}[^\n\p{L}]*$)(?=(?:[^\n\p{N}]*\p{N}){5,6}[^\n\p{N}]*$)(?=(?:[^\n@]*@){3}[^\n@]*$)[\p{L}\p{N} @]+$

这是一个demo

请注意,如果您不打算使用多行模式(m 标志),则可以删除 \n

前瞻中的 3 个条件:

  • (?=(?:[^\n\p{L}]*\p{L}){4}[^\n\p{L}]*$) - 此前瞻匹配(从输入字符串的开头)任何不是字母的序列,然后是字母 4 次(您可以在此处设置任何其他限制,然后查找非字母直到最后(如果找到更多,则失败)。
  • (?=(?:[^\n\p{N}]*\p{N}){5,6}[^\n\p{N}]*$) - 类似的前瞻,但现在,我们匹配非数字 + 数字 5 或 6 次,并确保以后没有数字。
  • (?=(?:[^\n@]*@){3}[^\n@]*$) - @.
  • 的逻辑相同

如果你只需要设置一个最小阈值,你不需要那些在前瞻结束时的否定字符类,例如(?=(?:[^\n@]*@){3}) 将匹配 3 个或更多 @,它只需要 3 @s。