Scala:正则表达式模式与花括号匹配?

时间:2018-02-25 16:59:28

标签: regex scala parsing curly-braces wml

所以我正在为我的作业创建一个类似WML的语言,作为第一步,我应该创建正则表达式来识别以下内容:

//single = "{"
//double = "{{"
//triple = "{{{"

这是我的第二个代码:

val double = "\\{\\{\\b".r

我的测试是:

println(double.findAllIn("{{ s{{ { {{{ {{ {{x").toArray.mkString(" "))

它不打印任何东西!它应该打印第一,第二,第五和第六个标记。我已经尝试了\ b和\ B的每一个组合,甚至是\ {{2,2}而不是\ {\ {但它仍然不起作用。任何帮助?

作为一个附带问题,如果我希望它只匹配第一个和第五个令牌,我还需要做什么?

1 个答案:

答案 0 :(得分:1)

我测试了你的代码(Scala 2.12.2 REPL),与你的“它不打印任何东西”语句相反,它实际上打印了来自“{{x”substring的“{{”。

这是因为x是一个单词字符,而\b匹配第二个{x之间的位置。请注意,与{不同,x不是单词字符。

根据this tutorial

  

它匹配一个称为“单词边界”的位置。这个匹配是零长度

     

有三种不同的职位符合词边界:

     

1)在字符串中的第一个字符之前,如果第一个字符是a   字符

     

...

至于解决方案,它取决于精确的定义,但外观似乎对我有用:

"(?<!\\{)\\{{2}(?!\\{)".r

它匹配“第一,第二,第五和第六标记”。表达式表示匹配“{{”不在前面,后面跟不是“{”。

对于附带问题:

"(?<![^ ])\\{\\{(?![^ ])".r //match `{` surrounded by spaces or line boundaries

或者,取决于您对“空间”的解释:

"(?<!\\S)\\{\\{(?!\\S)".r

匹配第1和第5个令牌。我不能使用积极的外观因为我想自动考虑行开头和结尾(边界)。因此,![^ ]的双重否定产生了隐含包含^$的效果。或者,您可以使用:

"(?<=^|\\s)\\{\\{(?=\\s|$)".r

您可以阅读有关外观here的内容。基本上它们将符号或表达匹配为边界;只是说他们匹配的东西,但不包括在匹配的字符串本身。

一些外观的例子

  • (?<=z)aaa匹配前面有z
  • 的“aaa”
  • (?<!z)aaa匹配前面没有z
  • 的“aaa”
  • aaa(?=z)匹配“aaa”后跟z
  • aaa(?!z)匹配“aaa”后面没有z

P.S。为了让您的生活更轻松,Scala有"""用于逃避,所以让我们说而不是:

"(?<!\\S)\\{\\{(?!\\S)".r

你可以:

"""(?<!\S)\{\{(?!\S)""".r