2014-12-22 3 views
3

У меня есть текст что-то вроде этого: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} 

Как я могу исправить мое регулярное выражение.

+1

Это не возможно производить 'TEXT2 text3' в одной игре (или группы).У вас может быть шаблон, который создает '{text2} {text3}' или тот, который заключает 'text2' в группе захвата 1,' text3' в группе захвата 2 и т. Д. - и в этом случае вы можете захватывать только ограниченное число слов , –

+0

Я отредактировал свой вопрос, потому что в третьем случае мне нужно продолжать группировку. –

ответ

3

Это очень выполнимо, хотя вы, возможно, захотите, чтобы убедиться, что вам действительно нужно сделать это с помощью регулярных выражений, так как результат не совсем красиво, и в значительной степени unmaintanable:

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

Основной трюк должен был использовать отрицательный lookbehind с нулевой шириной (например, (?<=\{), чтобы избежать соответствия '{').

Согласованный текст в группе 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} 
+0

Отлично! Спасибо! –

0

Вы можете использовать привязку \G, если scala поддерживает эту функцию.

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

DEMO

-3

Регулярные выражения являются излишеством для этого; они используются в 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}]) 

Это будет работать, даже если строка начинается с открытой скобки, потому что split будет генерировать пустой первый элемент.

Теперь вы можете обработать массив расщепление на закрывающей фигурной скобкой и принимать участие до скобкой:

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

Обратите внимание, что это не совсем устойчив к несбалансированные фигурные скобки, которая включает в себя случаи, когда скобка-заключенные сама строка содержит фигурные скобки. Поэкспериментируйте с моим последним примером против некоторых таких строк. Для этого вам нужно построить (тривиальный) парсер и решить, как вы собираетесь убежать или иначе закодировать встроенные фигурные скобки. Аналогично, если ваш пример на самом деле является упрощенной версией более сложного языка.

Смежные вопросы