我测试了您的代码(Scala 2.12.2 REPL),与您的“它不打印任何东西”语句相反,它实际上从“{{x”子字符串打印“{{”出现。
这是因为x
is 一个单词字符并且\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