2010-05-07 49 views
0

我有这样一个字符串“{一些|话|被|这里}”和“{其他|设置|的|词}”红宝石参数化的正则表达式

所以在一般的字符串由左大括号的,由管道和结束的大括号分隔的单词。

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

我愿做这样的事情:

@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包含哪些内容?

+2

条形支撑,在管道上分开。你可能的意思是'get_column(2)'=>''a'' – SilentGhost 2010-05-07 14:38:14

回答

2

因此,这是解决方案,我喜欢现在:

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

我们使用正则表达式,以确保该字符串格式是正确的,同时抓住了正确的列。

说明正则表达式的:

  • \A是字符串的beginnning和\Z是结尾,所以此正则表达式的enitre字符串匹配。
  • 由于花括号具有特殊含义,我们将它们转义为\{\}以匹配字符串开头和末尾的花括号。
  • 接下来,我们要跳过前n列 - 我们不关心它们。
    • 以前的专栏是字母后跟竖线一些数字,所以我们使用标准\w匹配一个字状的字符(包括数字和下划线,但为什么不)和*匹配任何数量的人。垂直条有特殊的含义,所以我们必须将其作为\|转义。由于我们想对此进行分组,因此我们将其全部包含在非捕获伙伴(?:\w*\|)?:使其不捕获)。
    • 现在我们有n以前的列,所以我们告诉正则表达式匹配使用计数正则表达式的列模式n次 - 只需在花括号后面放置一个数字。我们使用标准的字符串substition,所以我们只是把{#{n}}表示“符合以前的模式正好n倍。
  • 第一个非跳过栏后,这是我们关心的一个,所以我们把在捕获括号:(\w*)
  • 那么我们跳过列的其余部分,如果有的话:(?:\|\w*)*

捕获柱将其放入$1,所以我们返回值,如果正则表达式匹配。如果没有,我们返回零。 ,因为这个String没有n th柱。

在一般情况下,如果你想有更多的不仅仅是字在列(如"{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 

我们使用了类似的正则表达式,以确保该字符串包含一组列或引发错误。然后,我们从正面和背面剥离花括号(使用self[1 .. -2]限制从第一个字符开始到最后一个结束的子字符串),使用管道字符拆分列(使用.split('|')创建一个列数组) ,然后找到第n列(使用标准的数组查找[n])。

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