Ruby正则表达式中\A、\z和^ $的区别

232

在文档中我读到:

使用 \A 和 \z 匹配字符串的开头和结尾,使用 ^ 和 $ 匹配行的开头/结尾。

我将应用正则表达式来检查用户提交的用户名(或电子邮件)。我应该在模型中使用哪个表达式与validates_format_of一起使用?我不理解它们的区别:我一直使用^和$...


http://guides.rubyonrails.org/security.html#regular-expressions - Ivan Chau
4个回答

269
如果您要使用正则表达式进行验证,您应始终使用\A\z^$只会匹配到换行符之前的部分,这意味着它们可以使用像 me@example.com\n<script>dangerous_stuff();</script>这样的电子邮件地址仍然能够验证,因为正则表达式只看到\n之前的所有内容。
我的建议是先完全去除用户名或电子邮件中的换行符,因为几乎没有合法的原因需要保留它们。然后您可以安全地使用\A\z^$

14
@Ragmaanir是正确的,应该使用小写字母\z而不是\Z - Petr
13
谢谢!虽然我必须不同意你的建议:A)如果有适当的通用方法,请不要添加不必要的工作/处理,B)尤其不要这样做,因为它让你保持懒惰,无法区分两者。您可能并不总是能够进行字符串操作,只能使用正则表达式,所以请记住正确的方法,并知道它们之间的区别! - dooleyo
2
我不理解关于危险内容的例子,因为在任何情况下,都可以在字符串中包含危险内容,无论是否有换行符,这都是一个应该通过HTML清理和验证来修复的漏洞。 - Jayr Motta
3
@JayrMotta 这个演示展示的是,危险的东西会完全绕过你整个正则表达式检查。因此,即使你在正则表达式中检查危险的东西,如果你使用$来检查“字符串结尾”,它也会被绕过,而不是使用\z - Doctor Blue

203
根据Pickaxe的说明:

^匹配行的开头。

$匹配行的结尾。

\A匹配字符串的开头。

\z匹配字符串的结尾。

\Z匹配字符串的结尾,除非字符串以"\n"结束,在这种情况下,它会在"\n"之前匹配。

因此,应该使用\A和小写的\z。如果使用\Z,则可能会出现换行符,这不会有危险,但可能会破坏假定字符串中没有空格的算法。根据您的正则表达式和字符串长度限制,某些人可能会使用仅包含换行符的不可见名称。JavaScript的正则表达式实现将\A视为字面值'A' (参考)。因此,在那里要注意自己的测试。

24

示例演示区别

  1. /^foo$/ 匹配以下任意一个,/\Afoo\z/ 不匹配:
whatever1
foo
whatever2
foo
whatever2
whatever1
foo
  1. /^foo$//\Afoo\z/ 都匹配以下内容:
foo

20

字符串的起始和结束位置不一定与行的起始和结束位置相同。想象一下,如果您将以下内容用作测试字符串:

我的
名字

安德鲁

请注意,该字符串有多行 - ^$字符允许您匹配这些行的开头和结尾(基本上将\n字符视为分隔符),而\A\Z允许您匹配整个字符串的开头和结尾。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接