我正在尝试用REGEX验证PHP中的输入。我想检查输入中是否有%s
字符组,以及它是否只出现一次。否则,该规则将失败。
以下是我尝试过的:
preg_match('|^[0-9a-zA-Z_-'s:;,'.'?!'(')'p{L}(%s){1}]*$|u', $value);
(除此之外还有一些其他规则;我尝试过(%s){1}
部分,但它不起作用)。
我相信这是一个非常简单的解决方案,但我并不真正喜欢REGEX。。。谢谢你的帮助!
如果我理解你的问题,你需要积极的展望。前瞻性导致表达式只有在找到单个%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}]*$
正则表达式的其余部分还会查看整个字符串,并确保整个字符串仅由字符类中的字符组成(与原始正则表达式类似)。
我使用PHP的substra_count()函数完成了这项工作,遵循Johnyweb的建议,使用另一种方法来执行验证,因为REGEX的建议看起来相当复杂。
再次感谢!
或者,您可以将preg_match_all
与您的模式一起使用,并检查匹配的数量。如果是1,那么你就没事了——类似这样的东西:
$result = (preg_match_all('|^[0-9a-zA-Z_-'s:;,'.'?!'(')'p{L}(%s){1}]*$|u', $value) == 1)
试试这个:
'|^(?=(?:(?!%s).)*%s(?:(?!%s).)*$)[0-9_'s:;,.?!()'p{L}-]+$|u'
方括号内的(%s){1}
序列可能不会起到你认为的作用,但没关系,解决方案更复杂。事实上,{1}
不应该出现在正则表达式中的任何位置。它并不能像许多人所认为的那样,确保某件事只有一件。事实上,它对没有任何作用;这纯粹是一团糟。
编辑(回答注释):为了确保字符串中只存在特定序列中的一个,您必须主动检查每个字符,将其分类为-%s
的一部分或而不是-%s
的部分。为此,(?:(?!%s).)*
一次消耗一个字符,在之后,否定展望已经确认该字符不是%s
的开始。
当先行表达式的这一部分退出匹配时,字符串中的下一个必须是%s
。然后第二个CCD_ 16开始确认在字符串结束之前没有更多的CCD_。
别忘了前瞻表达式必须两端都锚定。因为前瞻性是主正则表达式的起始锚点之后的第一件事,所以不需要添加另一个^
。但是前瞻必须以其自己的$
锚结束。
如果你不"喜欢"正则表达式,为什么不用PHP解决这个问题?
对内置strpos()
的一次调用将告诉您该字符串是否匹配。如果它出现不止一次,第二个电话会告诉你。
这会让你更容易阅读,也让其他人更容易维护。