【问题标题】:Regular expression scan results don't register further regex hits?正则表达式扫描结果没有记录更多的正则表达式命中?
【发布时间】:2013-11-26 08:41:42
【问题描述】:

我正在用 Ruby 中的递归正则表达式解析伪 S 表达式。

经过一番搜索,我开始使用“Matching balanced parenthesis in Ruby using recursive regular expressions like perl”的答案中使用的正则表达式。正则表达式匹配正确,但结果表现出奇怪的行为。如果我尝试在任何结果上使用match,那么无论使用什么正则表达式,这些进一步的结果都将匹配整个测试字符串。如果我用字符串文字显式覆盖初始结果之一,则 match 会按预期工作。然而,结果条目的类无疑声称它是一个普通的香草字符串。这到底是怎么回事?

src = "(def foo 10) (+ foo 4 12)"

def parse(exp)

     expression =%r{
      (?<re>
        \(
          (?:
        (?> [^()]+ )
        |
        \g<re>
          )*
        \)
      )
    }x
     trans = ""
     exp.scan(expression) {|m|
      m[0].match(/\d/) {|m|
          trans += m.string
     }
     } 
     return trans
end

当然,这甚至还不能完全解析代码。我也知道尝试使用正则表达式健壮地解析代码并不是一个好主意,但我并不是想做出一个健壮的解决方案,只是一个 POC。

有谁知道是什么导致这些正则表达式行为不端?

【问题讨论】:

  • 这看起来是一个有趣的问题,但是您能否通过一个您看到的特定输出与您期望的输出示例来更新它?
  • 你考虑过像TreeTop这样的解析表达式语法吗?
  • @PeterAlfvin 今天晚些时候我会更新这个问题并验证你的答案。
  • @MarkThomas 最终版本不会解析任何东西,它会搭载 LISP 宏。现在我只关注目标语言结构而不是源语言功能。

标签: ruby regex


【解决方案1】:

来自MatchData 的方法string 返回一个“通过in 匹配的字符串的冻结副本”,而不是匹配的内容。每http://www.ruby-doc.org/core-2.0.0/MatchData.html#method-i-string

这就是您返回整个字符串的原因,因为您将每个初始匹配项添加到 trans

您可以通过在最里面的块中输入m 的值的打印语句来确认这一点。 match 正确匹配 1,然后是 4

【讨论】:

  • 你是正确的,m.string 不只返回匹配的子字符串......但是,这并不能解释其他行为,即字符串匹配它不应该匹配的正则表达式 at全部。我将在问题中提供更全面的示例。
  • 其实我不会那样做的。你的回答说明了一切。我一直在完全误解这种行为。谢谢!
猜你喜欢
  • 1970-01-01
  • 2016-01-23
  • 2019-11-19
  • 2012-01-06
  • 2016-09-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多