首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >带负前瞻的Scala正则表达式多行匹配

带负前瞻的Scala正则表达式多行匹配
EN

Stack Overflow用户
提问于 2014-07-16 02:37:57
回答 2查看 1.7K关注 0票数 0

我正在使用Scala的解析器组合器编写一个DSL。最近,我将基类从StandardTokenParsers更改为JavaTokenParsers,以利用regex的特性,我认为我需要完成最后一部分的拼图。(见使用scala StandardTokenParser解析分隔的多行字符串)

我要做的是提取一个由一些字符分隔的文本块(本例中为{{}} )。这个文本块可以跨越多行。到目前为止,我得到的是:

代码语言:javascript
复制
  def docBlockRE = regex("""(?s)(?!}}).*""".r)
  def docBlock: Parser[DocString] =
      "{{" ~> docBlockRE <~ "}}" ^^ { case str => new DocString(str) }}

其中DocString是我的DSL中的一个案例类。然而,这是行不通的。如果我按以下方式喂养它,它就会失败:

代码语言:javascript
复制
{{
abc
}}

{{
abc
}}

我不知道为什么会失败。如果我在解析器(http://jim-mcbeath.blogspot.com/2011/07/debugging-scala-parser-combinators.html)周围放置了一个Deubg包装器,就会得到以下内容:

代码语言:javascript
复制
docBlock.apply for token 
   at position 10.2 offset 165 returns [19.1] failure: `}}' expected but end of source found

如果我尝试一个带有多行分隔的单个块:

代码语言:javascript
复制
{{
abc
def
}}

然后,它也无法用以下方法进行解析:

代码语言:javascript
复制
docBlock.apply for token 
  at position 10.2 offset 165 returns [16.1] failure: `}}' expected but end of source found

如果删除DOTALL指令(?s),那么我可以解析多个单行块(这对我没有多大帮助)。

有没有办法将多行正则表达式与负前瞻相结合?

使用这种方法的另一个问题是,无论我做什么,结束分隔符必须在文本之外的一行上。否则,我会得到与上面看到的错误信息相同的错误信息。这几乎就像我所期望的那样,消极的展望并没有真正发挥作用。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2014-07-16 03:29:02

在以下方面:

代码语言:javascript
复制
scala> val rr = """(?s).*?(?=}})""".r
rr: scala.util.matching.Regex = (?s).*?(?=}})

scala> object X extends JavaTokenParsers {val r: Parser[String] = rr; val b: Parser[String] = "{{" ~>r<~"}}" ^^ { case s => s } }
defined object X

scala> X.parseAll(X.b, """{{ abc
     | def
     | }}""")
res15: X.ParseResult[String] =
[3.3] parsed: abc
def

更多的是表现出贪婪的不同:

代码语言:javascript
复制
scala> val rr = """(?s)(.*?)(?=}})""".r.unanchored
rr: scala.util.matching.UnanchoredRegex = (?s)(.*?)(?=}})

scala> def f(s: String) = s match { case rr(x) => x case _ => "(none)" }
f: (s: String)String

scala> f("something }} }}")
res3: String = "something "

scala> val rr = """(?s)(.*)(?=}})""".r.unanchored
rr: scala.util.matching.UnanchoredRegex = (?s)(.*)(?=}})

scala> def f(s: String) = s match { case rr(x) => x case _ => "(none)" }
f: (s: String)String

scala> f("something }} }}")
res4: String = "something }} "

展望只是意味着“确保这跟随我,但不要消耗它。”

消极的展望只是意味着它不会跟随我。

票数 2
EN

Stack Overflow用户

发布于 2014-07-16 02:42:38

要匹配{{the entire bracket}},请使用以下正则表达式:

代码语言:javascript
复制
(?s)\{\{.*?\}\}

参见演示中的匹配。

若要匹配{{inside the brackets},请使用以下命令:

代码语言:javascript
复制
(?s)(?<=\{\{).*?(?=\}\})

参见演示中的匹配。

解释

  • (?s)激活DOTALL模式,允许点跨行匹配。
  • .*?中的星号量词是由?“懒散”的,这样点就只能与所需的点匹配。如果没有?.*将获取最长的匹配,首先匹配整个字符串,然后只在需要的范围内回溯以允许下一个令牌匹配。
  • (?<=\{\{)是一个查找器,它断言前面的是{{
  • (?=\}\})是一种前瞻性,它断言接下来的是}}

参考

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/24771341

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档