Scala正则表达式 - 如何匹配花括号内部,但逃脱花括号本身

时间:2014-12-22 09:35:10

标签: regex scala

我的文字是这样的:

text {text10}
text {text1, text9}
anotherText [
{text2, text5}
{text3, text6}
{test4, text8}
]

这个正则表达式匹配我想要的一切:

val regex =  """(.*?) (\[.*?\]|\{(.*?)\})""".r

但是我有一个小问题。我不想自己匹配大括号。所以,我输出

val line = regex findAllIn configByLines
line.matchData foreach {
  m => println("output: "+m.group(2))
}
#output: {text10}
#output: {text1, text9}
#output: [{text2, text5} {text3, text6} {test4, text8}]

但是我希望将组(2)的输出作为

#output: text10
#output: text1, text9
#output: {text2, text5} {text3, text6} {text4, text8}

如何修复我的正则表达式。

3 个答案:

答案 0 :(得分:3)

这是非常可行的,虽然你可能想确保你真的需要使用正则表达式,因为结果不是很漂亮,而且非常难以理解:

val regex =  """[^\{\[]*[\{\[](((?<=\{)[^}]*)|((?<=\[)[^\]]*))[\}\]]""".r

主要技巧是使用零宽度负面后视(例如(?<=\{)),以避免匹配&#39; {&#39;本身)。

第1组中匹配的文字。

强制性REPL会议:

scala> val configByLines = """text {text10}
     | text {text1, text9}
     | anotherText [
     | {text2, text5}
     | {text3, text6}
     | {test4, text8}
     | ]"""
configByLines: String =
text {text10}
text {text1, text9}
anotherText [
{text2, text5}
{text3, text6}
{test4, text8}
]

scala> val regex =  """[^\{\[]*[\{\[](((?<=\{)[^}]*)|((?<=\[)[^\]]*))[\}\]]""".r
regex: scala.util.matching.Regex = [^\{\[]*[\{\[](((?<=\{)[^}]*)|((?<=\[)[^\]]*))[\}\]]

scala> val line = regex findAllIn configByLines.replace("\n", " ")
line: scala.util.matching.Regex.MatchIterator = non-empty iterator

scala> line.matchData foreach {
     |   m => println("output: "+m.group(1))
     | }
output: text10
output: text1, text9
output:  {text2, text5} {text3, text6} {test4, text8}

答案 1 :(得分:0)

如果scala支持此功能,您可以使用\G锚点。

(?:^(.*?) \[?|(?<!^)\G){?([\w]*)}?

DEMO

答案 2 :(得分:-2)

正则表达式对此有些过分;它们在Perl中用于这种解析,因为正则表达式引擎功能强大并带来了性能优势,但在JVM中,除非你真正需要它们,否则你不会通过使用正则表达式来赢得任何东西。所以我建议手动解析这个特定的例子。

把你的字符串分开并打开括号:

scala> "anotherText [{text2} {text3}]" split '{'
res1: Array[String] = Array(anotherText [, "text2} ", text3}])

丢掉第一个元素,因为前面没有左括号:

scala> ("anotherText [{text2} {text3}]" split '{').tail
res2: Array[String] = Array("text2} ", text3}])

即使字符串以左括号开头,这仍然有效,因为分割将生成一个空的第一个元素。

现在,您可以在右大括号上处理数组拆分并在大括号前取得部分:

scala> ("anotherText [{text2} {text3}]" split '{').tail map (_.split('}').head)
res3: Array[String] = Array(text2, text3)

请注意,这对于不平衡的大括号来说并不是很强大,其中包括括号括起的字符串本身包含大括号的情况。试试我的最后一个例子来反对一些​​这样的字符为此,您需要构建一个(普通的)解析器并决定如何转义或以其他方式编码嵌入式大括号。同样,如果您的示例实际上是一个相当复杂的语言的简化版本。