Как написать регулярное выражение для соответствия ((11 3) (96 15) (2 3)) - PullRequest
0 голосов
/ 11 июля 2011

Я пытаюсь сделать регулярное выражение, которое будет соответствовать:

((11 3) (96 15) (2 3) )

Пока у меня есть:

([^(|^)| |[A-Za-z])+

Но оно захватывает только 11, а не остальные.Также строка намного длиннее, я просто использовал ее небольшую часть, поэтому она повторяется в том же формате, но с разными номерами.Это то, что я до сих пор для программы хотя бы частично из этого:

regex expression("([^(|^)| |[A-Za-z])+");
string line2 = "((11 3) (96 15) (2 3) )";
if(regex_match(line2, expression))
    cout << "yes";
else
    cout << "no";

Ответы [ 3 ]

6 голосов
/ 11 июля 2011

В вашем примере строки числа , но в регулярном выражении используются буквы , это было задумано? Я полагаю, я бы использовал регулярное выражение что-то вроде этого:

\((\([0-9]+ [0-9]+\) )+\)

Если мы сломаем это, вот мой мыслительный процесс:

\(     // start with a literal "("
(      // create a group
\(     // another literal "("
[0-9]+ // one or more digits
       // a space (hard to spell out here
[0-9]+ // one or more digits
       // a space (hard to spell out here
\)     // a litteral ")" to match the opening
)      // close the group
+      // group must repeat one or more times
\)     // final closing ")"

РЕДАКТИРОВАТЬ: ОК, так как вы говорите, что иногда вторые числа не являются числами, то мы можем легко настроить регулярное выражение, чтобы выглядеть примерно так:

\((\([0-9]+ [A-Za-z0-9]+\) )+\)

если вам нужно избегать смешивания букв и цифр, вы можете сделать это:

\((\[0-9]+ ([A-Za-z]+|[0-9]+)\) )+\)
2 голосов
/ 11 июля 2011

Давайте создадим ваше выражение «с нуля».

Учитывая, что ваша конечная цель соответствует ((11 3) (96 15) (2 3) ), мы начнем с сопоставления гораздо более простого шаблона и продвинемся по одному шагу за раз:

\d        matches "1"
\d+       matches "11", or "3", or "96"
\d+ *\d+  matches "11 3" or "96 15"
\(\d+ *\d+\)           matches "(11 3)" or "(96 15)"
(\(\d+ *\d+\) *)*      matches "(11 3)(96 15) (2 3)"
\((\(\d+ *\d+\) *)*\)  matches "((11 3) (96 15) (2 3) )"

Примечание. Я не проверял этот ответ.Я опирался на документацию Boost.Regex для разработки этого ответа.

0 голосов
/ 11 июля 2011

Я решил это недавно, когда пытался сопоставить синтаксис, подобный 1-4,5,9,20-25.Результирующее регулярное выражение, по общему признанию, не простое:

/\G([0-9]++)(?:-([0-9]++))?+(?:,(?=[-0-9,]+$))?+/

Это выражение позволило мне постепенно собирать все совпадения в строку.

Мы можем применить тот же подход к вашемупроблема, но это чрезвычайно сложно как проверить, так и сопоставить ваш ввод данных.(Я не знаю, как это сделать. Если это сделает кто-то другой, я бы хотел посмотреть!) Но вы можете проверить ввод отдельно:

/\(\s*(\s*((\s*\d+\s+\d+\s*)\)\s*)+\s*\)/

См. Ответ Эвана за то, как это работает.\d эквивалентно [0-9] и \s эквивалентно [\r\n\t ].

Это инкрементное совпадение для извлечения чисел:

/\G\(?\s*(?:\(\s*(\d+)\s+(\d+)\s*\))(?:(?=\s*\(\s*\d+\s+\d+\s*\))|\s*\))/

Разбивается так, как:

/\G     # matches incrementally. \G marks the beginning of the string or the beginning of the next match.
 \(?\s* # matches first open paren; safely ignores it and following whiespace if this is not the first match.
 (?:    # begins a new grouping - it does not save matches.
   \(\s* # first subgroup open paren and optional whitespace.
   (\d+) # matches first number in the pair and stores it in a match variable.
   \s+   # separating whitespace
   (\d+) # matches second number in the pair and stores it in a match variable.
   \s*\) # ending whitespace and close paren
 )      # ends subgroup
 (?:    # new subgroup
   (?=  # positive lookahead - this is optional and checks that subsequent matches will work.
     \s*\(\s*\d+\s+\d+\s*\)  # look familiar?
   )    # end positive lookahead
   |    # if positive lookahead fails, try another match
   \s*\)\s* # optional ending whitespace, close paren
 )/     # ... and end subgroup.

Я не проверял это, но я уверен, что это сработает.Каждый раз, когда вы применяете выражение к заданной строке, оно будет извлекать каждую последующую пару чисел, пока не увидит последнюю закрывающую часть, и не будет использовать всю строку или остановится, если возникнет ошибка ввода.Возможно, вам придется уточнить это для Boost :: regex.Это Perl-совместимое регулярное выражение.

...