所以我正在为我的作业创建一个类似WML的语言,作为第一步,我应该创建正则表达式来识别以下内容:
//single = "{"
//double = "{{"
//triple = "{{{"
这是我的第二个代码:
val double = "\\{\\{\\b".r
我的测试是:
println(double.findAllIn("{{ s{{ { {{{ {{ {{x").toArray.mkString(" "))
它不打印任何东西!它应该打印第一,第二,第五和第六个标记。我已经尝试了\ b和\ B的每一个组合,甚至是\ {{2,2}而不是\ {\ {但它仍然不起作用。任何帮助?
作为一个附带问题,如果我希望它只匹配第一个和第五个令牌,我还需要做什么?
答案 0 :(得分:1)
我测试了你的代码(Scala 2.12.2 REPL),与你的“它不打印任何东西”语句相反,它实际上打印了来自“{{x”substring的“{{”。
这是因为x
是一个单词字符,而\b
匹配第二个{
和x
之间的位置。请注意,与{
不同,x
不是单词字符。
它匹配一个称为“单词边界”的位置。这个匹配是零长度
有三种不同的职位符合词边界:
1)在字符串中的第一个字符之前,如果第一个字符是a 字符
...
至于解决方案,它取决于精确的定义,但外观似乎对我有用:
"(?<!\\{)\\{{2}(?!\\{)".r
它匹配“第一,第二,第五和第六标记”。表达式表示匹配“{{”不在前面,后面跟不是“{”。
对于附带问题:
"(?<![^ ])\\{\\{(?![^ ])".r //match `{` surrounded by spaces or line boundaries
或者,取决于您对“空间”的解释:
"(?<!\\S)\\{\\{(?!\\S)".r
匹配第1和第5个令牌。我不能使用积极的外观因为我想自动考虑行开头和结尾(边界)。因此,!
和[^ ]
的双重否定产生了隐含包含^
和$
的效果。或者,您可以使用:
"(?<=^|\\s)\\{\\{(?=\\s|$)".r
您可以阅读有关外观here的内容。基本上它们将符号或表达匹配为边界;只是说他们匹配的东西,但不包括在匹配的字符串本身。
一些外观的例子
(?<=z)aaa
匹配前面有z
(?<!z)aaa
匹配前面没有z
aaa(?=z)
匹配“aaa”后跟z
aaa(?!z)
匹配“aaa”后面没有z
P.S。为了让您的生活更轻松,Scala有"""
用于逃避,所以让我们说而不是:
"(?<!\\S)\\{\\{(?!\\S)".r
你可以:
"""(?<!\S)\{\{(?!\S)""".r