繁体   English   中英

红宝石参数化正则表达式

[英]ruby parametrized regular expression

我有一个类似“ {some | words | are | here}”或“ {another | set | of | words}”的字符串

因此,一般而言,字符串由一个大括号,由管道分隔的单词和一个大括号组成。

获取该字符串的所选单词的最有效方法是什么?

我想做这样的事情:

@my_string = "{this|is|a|test|case}"
@my_string.get_column(0) # => "this"
@my_string.get_column(2) # => "is"
@my_string.get_column(4) # => "case"

方法get_column应该包含什么?

所以这是我现在喜欢的解决方案:

class String
  def get_column(n)
    self =~ /\A\{(?:\w*\|){#{n}}(\w*)(?:\|\w*)*\}\Z/ && $1
  end
end

我们使用正则表达式来确保字符串格式正确,同时获取正确的列。

正则表达式的解释:

  • \\A是字符串的开头, \\Z是结尾,因此此正则表达式与enitre字符串匹配。
  • 由于花括号具有特殊含义,因此我们将它们用\\{\\}进行转义,以匹配字符串开头和结尾处的花括号。
  • 接下来,我们要跳过前n列-我们不在乎它们。
    • 前一列是一些字母,后跟竖线,因此我们使用标准\\w来匹配类似单词的字符(包括数字和下划线,但为什么不能)和*来匹配任意数量的字母。 竖线有特殊含义,因此我们必须将其转义为\\| 由于我们希望将其分组,因此将其全部封装在非捕获的parens (?:\\w*\\|)?:使它不捕获)。
    • 现在我们有n列前面的列,因此我们使用regex计数让正则表达式匹配列模式n次-只需在模式后的花括号中放置一个数字即可。 我们使用标准的字符串替换,因此我们只需输入{#{n}}即可表示“与先前的模式完全匹配n次。
  • 之后的第一个非跳过列是我们关心的列,因此我们将其放在捕获括号中: (\\w*)
  • 然后我们跳过其余的列(如果存在): (?:\\|\\w*)*

捕获列会将其放入$1 ,因此如果正则表达式匹配,我们将返回该值。 如果不是,则返回nil,因为此String没有第n列。

通常,如果您想在栏目中不只包含单词(例如"{a phrase or two|don't forget about punctuation!|maybe some longer strings that have\\na newline or two?}" )),那么只需用[^|{}]替换正则表达式中的所有\\w ,这样您就可以使每一列都包含除大括号或竖线以外的任何内容。


这是我以前的解决方案

class String
  def get_column(n)
    raise "not a column string" unless self =~ /\A\{\w*(?:\|\w*)*\}\Z/
    self[1 .. -2].split('|')[n]
  end
end

我们使用类似的正则表达式来确保String包含一组列或引发错误。 然后,我们从前面和后面剥离花括号(使用self[1 .. -2]限制到从第一个字符开始到最后一个倒数第二个子字符串),使用竖线字符(使用.split('|') )分隔列.split('|')创建一个列数组),然后找到第n列(使用[n]使用标准Array查找)。

我只是想过,只要我使用正则表达式来验证字符串,就最好使用它来捕获列。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM