当前位置 : 主页 > 编程语言 > ruby >

使用变量分组解析带有ruby正则表达式的字符串的更优雅的方法?

来源:互联网 收集:自由互联 发布时间:2021-06-23
目前我有一个看起来像这样的正则表达式: ^(cat|dog|bird){1}(cat|dog|bird)?(cat|dog|bird)?$ 它匹配一长串单词的至少1个,最多3个实例,并通过相应的变量使每个组的匹配单词可用. 有没有办法修改
目前我有一个看起来像这样的正则表达式:

^(cat|dog|bird){1}(cat|dog|bird)?(cat|dog|bird)?$

它匹配一长串单词的至少1个,最多3个实例,并通过相应的变量使每个组的匹配单词可用.

有没有办法修改它,以便我可以返回字符串中每个单词的结果,而不预先指定组的数量?

^(cat|dog|bird)+$

有效,但只能分别返回最后一个匹配,因为只有一个组.

好的,所以我找到了解决方案.

它似乎不可能创建一个未知数量的组,所以我开始寻找另一种方法来实现预期的结果:能够判断一个字符串是否由给定列表中的单词组成;并匹配每个位置可能的最长单词.

我一直在阅读JeffreyE. F. Friedl的Mastering Regular Expressions,它为我揭示了一些事情.事实证明,基于NFA的Regexp引擎(如Ruby中使用的引擎)是顺序的,也是懒惰/贪婪的.这意味着您可以使用您为其选择的顺序来指定模式的匹配方式.这解释了为什么扫描返回变量结果,它正在查找列表中符合条件的第一个单词,然后转到下一个匹配.根据设计,它不是寻找最长的匹配,而是第一个.因此,为了纠正这一点,我需要做的就是将用于生成正则表达式的单词数组从字母顺序重新排序到长度顺序(从最长到最短).

array = %w[ as ascarid car id ]
list = array.sort_by {|word| -word.length } 
regexp = Regexp.union(list)

现在扫描找到的第一个匹配将是可用的最长的单词.通过扫描判断字符串是否仅包含列表中的单词也很简单:

if "ascarid".scan(regexp).join.length == word.length
  return true
else
  return false
end

感谢所有回复此问题的人,我希望这将有助于其他人.

网友评论