Scala:正则表达式模式与大括号匹配?
Scala: Regular Expression pattern match with curly braces?
所以我正在为我的作业创建一个类似于 WML 的语言,作为第一步,我应该创建正则表达式来识别以下内容:
//single = "{"
//double = "{{"
//triple = "{{{"
这是我的第二个代码:
val double = "\{\{\b".r
我的测试是:
println(double.findAllIn("{{ s{{ { {{{ {{ {{x").toArray.mkString(" "))
位它不打印任何东西!它应该打印第一个、第二个、第五个和第六个标记。我已经尝试了 \b 和 \B 的每一个组合,甚至 \{{2,2} 而不是 \{\{ 但它仍然无法正常工作。有帮助吗??
附带问题,如果我想让它只匹配第一个和第五个标记,我需要做什么?
我测试了您的代码 (Scala 2.12.2 REPL),与您的 "it doesn't print anything" 语句相反,它实际上从“{{x”子字符串中打印出“{{”。
这是因为x
是一个单词字符,而\b
匹配第二个{
和x
之间的位置。请记住 {
不是单词字符,与 x
.
不同
It matches at a position that is called a "word boundary". This match is zero-length
There are three different positions that qualify as word boundaries:
1) Before the first character in the string, if the first character is a
word character
...
至于解决方案,这取决于精确的定义,但环顾四周似乎对我有用:
"(?<!\{)\{{2}(?!\{)".r
匹配 "first, second, fifth and 6th token"。该表达式表示匹配“{{”之前和之后都没有“{”。
对于side-question:
"(?<![^ ])\{\{(?![^ ])".r //match `{` surrounded by spaces or line boundaries
或者,根据您对 "space" 的解释:
"(?<!\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
所以我正在为我的作业创建一个类似于 WML 的语言,作为第一步,我应该创建正则表达式来识别以下内容:
//single = "{"
//double = "{{"
//triple = "{{{"
这是我的第二个代码:
val double = "\{\{\b".r
我的测试是:
println(double.findAllIn("{{ s{{ { {{{ {{ {{x").toArray.mkString(" "))
位它不打印任何东西!它应该打印第一个、第二个、第五个和第六个标记。我已经尝试了 \b 和 \B 的每一个组合,甚至 \{{2,2} 而不是 \{\{ 但它仍然无法正常工作。有帮助吗??
附带问题,如果我想让它只匹配第一个和第五个标记,我需要做什么?
我测试了您的代码 (Scala 2.12.2 REPL),与您的 "it doesn't print anything" 语句相反,它实际上从“{{x”子字符串中打印出“{{”。
这是因为x
是一个单词字符,而\b
匹配第二个{
和x
之间的位置。请记住 {
不是单词字符,与 x
.
It matches at a position that is called a "word boundary". This match is zero-length
There are three different positions that qualify as word boundaries:
1) Before the first character in the string, if the first character is a word character
...
至于解决方案,这取决于精确的定义,但环顾四周似乎对我有用:
"(?<!\{)\{{2}(?!\{)".r
匹配 "first, second, fifth and 6th token"。该表达式表示匹配“{{”之前和之后都没有“{”。
对于side-question:
"(?<![^ ])\{\{(?![^ ])".r //match `{` surrounded by spaces or line boundaries
或者,根据您对 "space" 的解释:
"(?<!\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