我正在尝试使用REGEX验证PHP中的输入。我想检查输入中是否包含%s
字符组,并且只显示一次。否则,规则应该失败。
这是我尝试过的:
preg_match('|^[0-9a-zA-Z_-\s:;,\.\?!\(\)\p{L}(%s){1}]*$|u', $value);
(除此之外还有一些其他规则;我已经尝试了(%s){1}
部分,但它不起作用。)
我相信这是一个非常简单的解决方案,但我并没有真正进入REGEX ......谢谢你的帮助!
答案 0 :(得分:4)
如果我理解你的问题,你需要一个积极的前瞻。前瞻导致表达式仅在找到单个%s时才匹配。
preg_match('|^(?=[^%s].*?[%s][^%s]*$)[0-9a-zA-Z_-\s:;,\.\?!\(\)\p{L}(%s){1}]*$|u', $value);
我将解释每个部分的工作原理
^(?=[^%s].*?[%s][^%s]*$)
是零宽度断言 - (?=regex)
是一个积极的先行 - (意味着它必须匹配,但不会“吃掉”任何字符)。这意味着整行只能有1 %s
。
[0-9a-zA-Z_-\s:;,\.\?!\(\)\p{L}(%s){1}]*$
正则表达式的剩余部分也会查看整个字符串,并确保整个字符串仅由字符类中的字符组成(就像您的原始正则表达式一样)。
答案 1 :(得分:2)
我设法用PHP的substr_count()函数执行此操作,遵循 Johnsyweb 建议使用替代方法执行验证,因为REGEX的建议看起来相当复杂。
再次感谢你!
答案 2 :(得分:1)
或者,您可以在模式中使用preg_match_all
并检查匹配数量。如果它是1,那么你没事 - 就像这样:
$result = (preg_match_all('|^[0-9a-zA-Z_-\s:;,\.\?!\(\)\p{L}(%s){1}]*$|u', $value) == 1)
答案 3 :(得分:1)
试试这个:
'|^(?=(?:(?!%s).)*%s(?:(?!%s).)*$)[0-9_\s:;,.?!()\p{L}-]+$|u'
方括号内的(%s){1}
序列可能不会按照您的想法执行,但不要紧,解决方案更复杂。实际上,{1}
永远不会出现在正则表达式中的任何位置。它不能确保只有一个东西,正如许多人所认为的那样。事实上,它没有任何;这是纯粹的混乱。
编辑(回答评论):为了确保字符串中只存在一个特定序列,您必须主动检查每个字符,将其分类为%s
的部分或不部分 - %s
。为此,(?:(?!%s).)*
一次消耗一个字符,在之后否定前瞻已确认该字符不是%s
的开头。
当前瞻表达式的那一部分退出匹配时,字符串中的下一个内容必须是%s
。然后第二个(?:(?!%s).)*$
开始确认在字符串结束之前不再有%s
个序列。
不要忘记,前瞻表达式必须锚定在两端。因为前瞻是主正则表达式的起始锚之后的第一件事,所以你不需要添加另一个^
。但是前瞻必须以自己的$
锚结束。
答案 4 :(得分:0)