Ruby - 正则表达式匹配括号?

Joh*_*son 9 ruby regex brackets

我试图弄清楚一个字符串是否有正确的括号.

为此,我使用以下三个支架对.

[]
()
{}
Run Code Online (Sandbox Code Playgroud)

只要格式正确,括号也可以嵌套.

)([]{} - Does not have properly closed brackets because )( is reverse order

[()] - Does contain properly closed brackets.
Run Code Online (Sandbox Code Playgroud)

我尝试过使用正则表达式,经过一些摸索后,我得到了这个.

[^\(\[]*(\(.*\))[^\)\]]*
Run Code Online (Sandbox Code Playgroud)

但是,这有一些问题.

它只匹配括号但不匹配括号

我不明白为什么它与括号不匹配.

在我的例子中,我清楚地在括号前使用了反斜杠.

输入

[] - true
[()] - true (nested brackets but they match properly)
{} - true
}{ - false (brackets are wrong direction)
}[]} - false (brackets are wrong direction)
[[]] - true (nested brackets but they match properly
Run Code Online (Sandbox Code Playgroud)

saw*_*awa 9

non_delimiters = /[^(){}\[\]]*/
Paired = /\(#{non_delimiters}\)|\{#{non_delimiters}\}|\[#{non_delimiters}\]/
Delimiter = /[(){}\[\]]/

def balanced? s
  s = s.dup
  s.gsub!(Paired, "".freeze) while s =~ Paired
  s !~ Delimiter
end

balanced?(")([]{}")
# => false
balanced?("[]")
# => true
balanced?("[()]")
# => true
balanced?("{}")
# => true
balanced?("}{")
# => false
balanced?("}[]}")
# => false
balanced?("[[]]")
# => true
Run Code Online (Sandbox Code Playgroud)


Jef*_*ice 6

这可能是一个正则表达式的坏用例,我会使用一个简单的堆栈解析器.

def matching_brackets?(a_string)
  brackets =  {'[' => ']', '{' => '}', '(' => ')'}
  lefts = brackets.keys
  rights = brackets.values
  stack = []
  a_string.each_char do |c|
    if lefts.include? c
      stack.push c
    elsif rights.include? c
      return false if stack.empty?
      return false unless brackets[stack.pop].eql? c
    end
  end
  stack.empty?
end

matching_brackets? "[]"
matching_brackets? "[()]"
matching_brackets? "{}"
matching_brackets? "}{"
matching_brackets? "}[]}"
matching_brackets? "[[]]"
matching_brackets? "[[{]}]"
Run Code Online (Sandbox Code Playgroud)

编辑:Cary Swoveland - 写实际代码并让人们批评它: - ?

更新:我的检查中有一个讨厌的小虫子,看看结束的角色是否与开头的角色相匹配.固定它!


Aiv*_*ean 5

根据这篇文章,2.0版本的Ruby支持递归regexp.这意味着您可以使用特定\g<0>于Ruby的令牌在正则表达式的任何位置递归匹配整个正则表达式.这种方法可以有效地模拟堆栈以解决您的任务.

这是由此产生的正则表达式: [^(){}\[\]]*(\((\g<0>)?\)|\{(\g<0>)?\}|\[(\g<0>)?\])?[^(){}\[\]]*

此更新版本处理如下情况:[(){}]当多个括号组处于同一级别时.感谢@Jonny 5指出这个案例:

 [^(){}\[\]]*((\((\g<0>)?\)|\{(\g<0>)?\}|\[(\g<0>)?\])?[^(){}\[\]]*)*
Run Code Online (Sandbox Code Playgroud)

此表达式需要检查整个输入字符串是否匹配.部分匹配意味着在字符串的某个点处括号排序中存在错误.

这是其他版本,不需要检查整个输入字符串是否匹配:

 \A([^(){}\[\]]*((\((\g<1>)?\)|\{(\g<1>)?\}|\[(\g<1>)?\])?[^(){}\[\]]*)*)\Z
Run Code Online (Sandbox Code Playgroud)

您可能会注意到它尝试匹配相应的括号对,然后递归匹配自身.我在这里尝试了它似乎工作.我不是Ruby工程师所以我不能运行实际的Ruby测试,但希望它没有必要.