Ruby正则表达式:即使没有m修饰符,^也可以匹配行的开头吗?

10

我使用的是 Ruby 1.8.7。我正在使用一个带有 ^ 的正则表达式来匹配字符串开头的模式。问题在于,如果该模式在字符串中的 任何一行 处被找到,它仍然会匹配成功。如果我使用了 'm' 修饰符,那么这种行为就可以解释,但实际上我没有使用:

$ irb
irb(main):001:0> str = "hello\ngoodbye"
=> "hello\ngoodbye"
irb(main):002:0> puts str
hello
goodbye
=> nil
irb(main):004:0> str =~ /^goodbye/
=> 6

我这里做错了什么?


4
很棒的资源... http://rubular.com/ - Tony Fontenot
4个回答

24
  • 每行开头:^
  • 每行结尾:$
  • 字符串开头:\A
  • 字符串结尾:\z

17

13

你的困惑是合理的。在大多数正则表达式语法中,^ 等同于 \A$ 等同于 \Z,并且你必须设置 "multiline" 标志才能使它们具有其它含义(即行边界)。在 Ruby 中,^$ 总是匹配行边界。

更增加混淆的是,Ruby 有一些它称之为“multiline”的模式,但实际上它是其他所有人都称之为“单行”或“DOTALL”模式:它改变了元字符 . 的含义,允许它匹配行分隔符字符(例如 \r\n)以及所有其他字符。


哪些正则表达式的风格具有您所描述的行为? - Wayne Conrad
1
@Wayne:所有其他 Perl 派生品都是这样工作的:Perl、PHP、Python、JavaScript、Java、.NET... 如果它有一个“多行”模式,那就是它的意思:^ 变成了“行首”,$ 变成了“行尾”。我并不是说 Ruby 的方法是错的;顺便说一句,我只是希望他们没有像他们所做的那样混淆了名称。唯一真正做得好的风格是 Perl 6/Parrot,它消除了“多行”和“单行”模式。 - Alan Moore
1
是的,我习惯于在C和Perl中使用正则表达式,它们使用^的方式与Ruby使用\A相同。我曾认为C的正则表达式库是“权威”的,显然我错了。感谢你的回答。 - SteveRawlinson
此答案已添加到Stack Overflow正则表达式FAQ,位于“修饰符”下。 - aliteralmind
这绝对是最好的答案,因为它还解释了大多数学习Ruby并且已经熟悉其他语言中正则表达式的程序员会遇到的困惑。 - Mecki

2
"

"是行的开头。要实现您想要的效果,您可以拆分字符串并仅测试第一行。但我认为存在更好的方法。

"
str.split("\n")[0] =~ /^hello/

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