Регулярное выражение для взятия строки в скобках с кавычками - PullRequest
0 голосов
/ 15 января 2020

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

  1. [ "Italy" ] * 5 - [ "France","Paris" ] + 2 -> Матч 1: [ "Italy" ], Матч 2: [ "France","Paris" ]
  2. 3*12 * ["Country"] + ["City".] * 2 + [""] -> Матч 1: ["Country"], Матч 2: [""]
  3. [Madrid] -> Не совпадает
  4. ["Spain12"] * ["Name "Industry""] -> Матч 1: ["Spain12"], Матч 2: ["Name "Industry""]
  5. "My issue" / ["Error] ["some!+ name"]"] * 3 + 4 -> Матч 1: ["Error] ["some!+ name"]"]

Я пробовал это

\[\s*\"(.*?)\"\s*\]

Но в случаи 2 и 5 дают мне неправильный результат ["City".] * 2 + [""] и ["Error ]["some name"], но нужны ["Error] ["some name"]"]

Я пытался это

\[(?:[^\]\[]+|\[(?:[^)(]+|\([^)(]*\])*\])*\]

Но ошибаюсь в 2 и 5 вариантов тоже

PS: строка в скобках может содержать любые цифры, символы и буквы

1 Ответ

0 голосов
/ 15 января 2020

Вот решение, которое использует балансировочные группы, особенность. NET Regex, которая позволяет использовать стек, чтобы убедиться, что разделители, в данном случае [\s*" и "\s*], сбалансированы. Это делает все ваши совпадения правильными и должно быть довольно хорошо масштабируемым.

\[\s*"(?>(?!\[\s*"|"\s*]).|\[\s*"(?<Depth>)|"\s*](?<-Depth>))*(?(Depth)(?!))"\s*]

Разбивка этого регулярного выражения выглядит следующим образом:

\[\s*"            match the first delimiter
(?>               start atomic group (no backtracking allowed)
(?!\[\s*"|"\s*]). look ahead, make sure next character isn't a delimiter, then capture that character
|\[\s*"(?<Depth>) alternatively, capture an opening delimiter and push it to the <Depth> stack
|"\s*](?<-Depth>) alternatively, capture a closing delimiter and pop the top of the <Depth> stack
)*                close atomic group, repeat it 0 or more times
(?(Depth)(?!))    if the Depth stack has anything in it, fail the match
"\s*]             capture the final closing delimiter

разделители просты: \[ - открывающая скобка, затем \s* любое количество пробелов, затем " кавычка. Открывающая скобка должна быть исключена, потому что она имеет особое значение в Regex, но закрывающая скобка, используемая в закрывающем разделителе, необязательно должна быть связана с тем, что ее специальное значение связано с открывающей скобкой, поэтому закрывающий разделитель проще: "\s*] , только обратная открывающей.

Используя это, вы получите следующие совпадения:

"My issue" / ["Error] ["some!+ name"]"] * 3 + 4  -> ["Error] ["some!+ name"]"]
3*12 * ["Country"] + ["City".] * 2 + [""]        -> ["Country"] , [""]
["Spain12"] * ["Name "Industry""]                -> ["Spain12"] , ["Name "Industry""]
[  "Italy"  ] * 5 - [  "France","Paris" ] + 2    -> [  "Italy"  ] , [  "France","Paris" ]
[Madrid]                                         -> NO MATCHES

РЕДАКТИРОВАТЬ: Для получения дополнительной информации о балансировочных группах, см. этот замечательный ответ:

Что такое балансировочные группы регулярного выражения?

...