似乎HTML5 spec (and therefore ECMA262)允许<input type="text" pattern="[0-9]/[0-9]" />
匹配字符串'0/0',即使正斜杠没有被转义。像Drupal这样的Web应用程序希望为不支持HTML5的浏览器提供服务器端验证,例如:
<?php
preg_match('/^(' . $pattern . ')$/', $value);
?>
不幸的是,字符串'[0-9] / [0-9]'不是有效的PRCE正则表达式。似乎大多数(如果不是全部)支持HTML5的浏览器都支持pattern="[0-9]/[0-9]"
和 pattern="[0-9]\/[0-9]"
这引出了一个问题 - 我们可以使用什么作为分隔符来针对Perl运行此模式风格正则表达式?
我们已经提交了bug report against the W3C spec,但这里的浏览器有误吗?是否需要澄清HTML5规范?我们可以在PHP中使用解决方法吗?
答案 0 :(得分:4)
如果您使用#
而非/
作为分隔符,则它是一个有效的正则表达式。例如:
preg_match('#^('.$pattern.')$#', $value);
答案 1 :(得分:4)
我建议使用"\xFF"
字节作为模式分隔符,因为在UTF-8字符串中不允许使用它,因此我们可以确定它不会出现在模式中。因为preg_match不理解UTF-8,所以不会造成麻烦。
示例:preg_match("\xFF$pattern\$\xFFADmsu", $subject);
请注意ADmsu
修饰符并添加$
。 u
修饰符仅在模式中需要有效的UTF-8字节,但在周围的分隔符中不需要。
答案 2 :(得分:3)
PCRE的一个问题是几乎任何分隔符对于开始和结束标记都是合法的,这取决于使其余的转义更容易的原因。所以#foo#是合法的,/ foo /是合法的,!foo!是合法的(我认为)等等,我会说,无论如何,正确的理由是非常危险的。这听起来像是一个没有指定的HTML5规范错误。
也许在PHP中,扫描字符串并从字符串中不存在的白名单中选择分隔符? (例如,如果没有/使用它,如果有使用#,如果那里使用%等等)
答案 3 :(得分:2)
我认为chr(0)
可以正常工作。编辑:没有。但chr(1)
确实有用。
答案 4 :(得分:0)
鉴于PHP应用程序(在这种情况下是Drupal)正在生成输入字段,似乎解决方法是按照以下方式执行某些操作:
$pattern = '[0-9]/[0-9]';
...
$cleanPattern = preg_replace('/\//', '\\/', $pattern);
preg_match('/' . $cleanPattern . '/', $subject, $matches);
我无法想到这种情况不起作用的情况,/
被用作表达式中的文字。
HTML5规范遵循法律模式规范的ECMA262:
如果指定,则属性的值必须与JavaScript Pattern生成匹配。 [ECMA262]
由于ECMA262中定义了BNF,因此完全解析器(而不是使用PCRE)似乎是最安全的方法。
答案 5 :(得分:0)
只需将其括在方括号或括号中(是的,这很奇怪!):
<?php
preg_match('(^' . $pattern . '$)', $value);
?>
手册指出您可以使用所有对应的对:http://php.net/manual/en/regexp.reference.delimiters.php
乍一看并不容易,但是显然可以处理介于两者之间的任何字符。例如,'(^(foo|bar)$)'
作为最终的正则表达式:^(foo|bar)$
,没有任何潜在的风险转义。