正则表达式捕获字符串到ruby方法参数

时间:2014-07-25 17:52:43

标签: ruby regex

我正在寻找正则表达式来捕获这些字符串示例:

first_paramenter, first_hash_key: 'class1 class2', second_hash_key: true
first_argument, single_hash_key: 'class1 class2'
first_argument_without_second_argument

模式规则是:

  • 字符串必须从某个单词(第一个参数)/^(\w+)/
  • 开始
  • 第二个参数是可选的
  • 如果提供了第二个参数,fisrt参数后必须有一个逗号
  • 第二个参数是哈希,包含键和值。值可以是truefalse或由引号
  • 括起来的字符串
  • 哈希键必须以字母
  • 开头

我正在使用这个正则表达式,但它只与第二个例子匹配:

^(\w+),(\s[a-z]{1}[a-z_]+:\s'?[\w\s]+'?,?)$

3 个答案:

答案 0 :(得分:2)

我会选择以下内容:

^(\w+)(?:, ([a-z]\w+): ('[^']*')(?:, ([a-z]\w+): (\w+))?)?

Here's a Rubular example

(?:...)创建非捕获组,我们可以使用?轻松测试其存在。这样可以轻松测试可选块。

([a-z]\w+)是一种简单的说法,它必须以字母“#34;同时允许正常的alpha,数字和" _"。

至于测试"值可以是true,false或用引号括起来的字符串",我会在捕获后在代码中执行此操作。创建复杂模式太容易了,以后无法维护它。使用简单的方法更好,然后看看你是否得到了你所期望的,而不是试图在正则表达式中强制执行它。


  

在第三个例子中,你的正则表达式返回5个匹配。如果只返回一个会更好。它有可能吗?

我不确定你在问什么。这将返回每个捕获的单个捕获,但是如果您要捕获要发送到方法的参数,那么为什么您对我没有任何意义:

/^(\w+(?:, [a-z]\w+: '[^']*'(?:, [a-z]\w+: \w+)?)?)/

http://rubular.com/r/GLVuSOieI6

答案 1 :(得分:1)

你有基本的想法,那里有一堆小错误

/^(\w+)(,\s[a-z][a-z_]+:\s('[^']*'|true|false))*$/

说明:

/^(\w+)             # starts with a word
  (
    ,\s             # the comma goes _inside_ the parens since its optional
    [a-z][a-z_]+:\s # {1} is completely redundant
    (               # use | in a capture group to allow different possible keys
      '[^']*' |     # note that '? doesn't make sure that the quotes always match
      true    |
      false
    )
  )*$/x              # can have 0 or more hash keys after the first word

答案 2 :(得分:1)

在使用单个正则表达式攻击整个字符串或使用一个或多个String方法破坏字符串之间经常可以选择,然后分别执行每个部分。后一种方法通常使调试和测试更容易,并且还可以使代码对于凡人来说是可理解的。当然,这总是一种判断,但我认为这个问题很适合分而治之的方法。我就是这样做的。

<强>代码

def match?(str)
  a = str.split(',')
  return false unless a.shift.strip =~ /^\w+$/
  a.each do |s|
    return false unless  ((key_val = s.split(':')).size == 2) &&
                           key_val.first.strip =~ /^[a-z]\w*$/ &&
                           key_val.last.strip =~ /^(\'.*?\'|true|false)$/
  end
  true
end

<强>实施例

match?("first_paramenter, first_hash_key: 'class1 class2',
                          second_hash_key: true")
  #=>true
match?("first_argument, single_hash_key: 'class1 class2'")
  #=>true
match?("first_argument_without_second_argument")
  #=>true
match?("first_parameter, first_hash_key: 7")
  #=>false
match?("dogs and cats, first_hash_key: 'class1 class2'")
  #=>false
match?("first_paramenter, first_hash_key: 'class1 class2',
                          second_hash_key: :true")
  #=>false