0

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

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

这是我的第二个代码:

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

我的测试是:

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

位它不打印任何东西!它应该打印第一个、第二个、第五个和第六个令牌。我已经尝试了 \b 和 \B 甚至 \{{2,2} 而不是 \{\{ 的每一个组合,但它仍然无法正常工作。有什么帮助吗??

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

4

1 回答 1

1

我测试了您的代码(Scala 2.12.2 REPL),与您的“它不打印任何东西”语句相反,它实际上从“{{x”子字符串打印“{{”出现。

这是因为xis 一个单词字符并且\b匹配second和之间的位置。请记住,这不是单词字符,不像.{x{x

按照本教程

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

有资格作为单词边界的三个不同位置:

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

...

至于解决方案,它取决于精确的定义,但环顾四周似乎对我有用:

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

它匹配“第一个、第二个、第五个和第六个令牌”。该表达式表示匹配“{{”不在“{”之前且不在“{”之后。

对于附带问题:

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

或者,根据您对“空间”的解释:

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

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

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

您可以在此处阅读有关环视的信息。基本上它们匹配符号或表达式作为边界;只是说它们匹配内容,但不将其包含在匹配的字符串本身中。

环顾四周的一些例子

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

PS 为了让你的生活更轻松,Scala 有"""转义功能,所以让我们说:

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

你可以:

"""(?<!\S)\{\{(?!\S)""".r
于 2018-02-25T17:24:45.370 回答