返回 Ruby 正则表达式的第一个匹配项

Posted

技术标签:

【中文标题】返回 Ruby 正则表达式的第一个匹配项【英文标题】:Return first match of Ruby regex 【发布时间】:2010-10-05 21:30:25 【问题描述】:

我正在寻找一种在 Ruby 中对字符串执行正则表达式匹配并在第一次匹配时使其短路的方法。

我正在处理的字符串很长,从看起来标准的方式(match 方法)来看,它会处理整个事情,收集每个匹配项,并返回一个包含所有匹配项的 MatchData 对象。

match = string.match(/regex/)[0].to_s

【问题讨论】:

【参考方案1】:

你可以试试String#[](如variableName[/regular expression/])。

这是 IRB 的示例输出:

names = "erik kalle johan anders erik kalle johan anders"
# => "erik kalle johan anders erik kalle johan anders"
names[/kalle/]
# => "kalle"

【讨论】:

这不是在做匹配并在幕后返回第一个结果吗? 在对各种长度的字符串进行了一些基准测试并查看了 C 源代码之后,结果发现 Regex.match 确实短路了,并且只找到了第一个匹配项。 很好,不知道这个快捷方式。 是否有关于此快捷方式的文档?我在高处和低处搜索了我认为是一个相对简单的任务,并且在找到这个之后才解决了我的问题。谢谢! @dmourati 您可以在String#[] 中找到此功能。感谢您询问该文档,因为在阅读该文档时我发现了 capture 参数——它可以让您返回捕获而不是完整匹配。【参考方案2】:

你可以使用[]:(类似于match

"foo+account2@gmail.com"[/\+([^@]+)/, 1] # matches capture group 1, i.e. what is inside ()
# => "account2"
"foo+account2@gmail.com"[/\+([^@]+)/]    # matches capture group 0, i.e. the whole match
# => "+account2"

【讨论】:

【参考方案3】:

如果只有匹配的存在很重要,你可以选择

/regexp/ =~ "string"

不管怎样,match 应该只返回第一个命中,而scan 搜索整个字符串。因此,如果

matchData = "string string".match(/string/)
matchData[0]    # => "string"
matchData[1]    # => nil - it's the first capture group not a second match

【讨论】:

如果您可以使用 perlish $1 等,那么 =~ 可以很好地返回匹配项。【参考方案4】:

我还不确定这个功能是真棒还是完全疯狂,但你的正则表达式可以定义局部变量。

/\$(?<dollars>\d+)\.(?<cents>\d+)/ =~ "$3.67" #=> 0
dollars #=> "3"

(取自http://ruby-doc.org/core-2.1.1/Regexp.html)。

【讨论】:

很棒的功能!正是我需要的 警告:它仅在 regex =~ string 时有效,在 string =~ regex 时无效【参考方案5】:

正则表达式 (regex) 只不过是一个有限状态机 (FSM)。

FSM 试图回答“这种状态是否可能?”的问题

它一直尝试进行模式匹配,直到找到匹配项(成功),或者直到探索了所有路径但没有找到匹配项(失败)。

关于成功,问题是“这种状态是否可能?”已回答“是”。因此不需要进一步的匹配并且正则表达式返回。

有关更多信息,请参阅 this 和 this。

进一步:here is an interesting example 演示正则表达式的工作原理。在这里,正则表达式用于检测给定数字是否为素数。这个例子是用 perl 编写的,但也可以用 ruby​​ 编写。

【讨论】:

以上是关于返回 Ruby 正则表达式的第一个匹配项的主要内容,如果未能解决你的问题,请参考以下文章

正则表达式匹配第一个非重复字符

从正则表达式仅返回部分匹配项

从正则表达式仅返回部分匹配项

C ++正则表达式替换第一个匹配项

Power BI R 脚本正则表达式仅返回第一个匹配项

将 dict 值读取为正则表达式,返回匹配项