Регулярное выражение с -, ::, ( и )

Мне нужно разделить строку

(age-is-25::OR::last_name-is-qa6)::AND::(age-is-20::OR::first_name-contains-test)

в

string[0] = (age-is-25::OR::last_name-is-qa6)

строка[1] = И

string[2] = (age-is-20::OR::first_name-contains-test)

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

Используя следующее регулярное выражение, Matcher.groupCount() возвращает 2, но присваивание результатов массиву возвращает нуль в качестве элементов.

Pattern pattern = Pattern.compile((\\)::)?|(::\\()?);

Я попытался разделить его с помощью :: или :: (.

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


person aradhak    schedule 11.06.2012    source источник
comment
Обобщение этой проблемы эквивалентно разбору выражений с регулярным выражением, что невозможно: регулярное выражение недостаточно мощно для этого.   -  person Sergey Kalinichenko    schedule 11.06.2012
comment
Это не глупо, если вы действительно что-то пробовали :) Отличная работа, если сначала попробовать что-то, прежде чем спрашивать.   -  person Ewald    schedule 11.06.2012
comment
как его можно разделить на :: только вокруг AND, не помещая этот AND в этот сплиттер??   -  person dantuch    schedule 11.06.2012
comment
Есть ли особая причина, по которой вам нужно регулярное выражение, или это просто потому, что вы думаете, что это будет проще, чем самостоятельно анализировать строку? По моему опыту, код синтаксического анализа строк часто пишется быстрее и проще в отладке, чем регулярные выражения.   -  person Daniel Pryden    schedule 11.06.2012
comment
@dasblinkenlight не обязательно, если речь идет о разделении вещей между скобками и остальными.   -  person MarioDS    schedule 11.06.2012
comment
@DanielPryden: Сначала я пытался разобрать строку, но поскольку она слишком сложная, я подумал, что регулярное выражение здесь лучше сработает.   -  person aradhak    schedule 11.06.2012
comment
@Catherine: Учитывая структуру строки, которую вы показали, простой лексер (который вы можете сделать с регулярным выражением, хотя вам это не нужно) в сочетании с простым парсер рекурсивного спуска должен помочь. К сожалению, сейчас я печатаю на телефоне, иначе приведу пример.   -  person Daniel Pryden    schedule 11.06.2012


Ответы (5)


Вы можете использовать положительный просмотр вперед и просмотр назад, чтобы сопоставить первую и последнюю круглые скобки.

String str = "(age-is-25::OR::last_name-is-qa6)::AND::(age-is-20::OR::first_name-contains-test)";

for (String s : str.split("(?<=\\))::|::(?=\\()"))
    System.out.println(s);

Выходы:

(age-is-25::OR::last_name-is-qa6)
AND
(age-is-20::OR::first_name-contains-test)

Однако небольшое замечание: похоже, вы анализируете какой-то рекурсивный язык. Регулярные выражения не годятся для этого. Если вы выполняете расширенный синтаксический анализ, я бы порекомендовал вам рассмотреть другие методы синтаксического анализа.

person dacwe    schedule 11.06.2012
comment
Забавно, как это первый ответчик, который не делает диких предположений. Он явно лучше знаком с расширенными регулярными выражениями и все же тестирует. В остальном просто попробуйте это, и если вам повезет, это сработает. - person MarioDS; 11.06.2012
comment
@dacwe действительно один из умных ответов, приятель. +1 к нему. - person Android Killer; 11.06.2012
comment
@dacwe: Большое спасибо! Кстати, я не понимаю использование ?‹= и ?= в регулярном выражении. Я никогда не видел их ни в одном из учебников. Не могли бы вы объяснить, или еще вы можете указать URL-адрес, откуда я мог бы получить некоторую информацию об этом? Спасибо еще раз. - person aradhak; 11.06.2012
comment
Я думаю, что regular-expressions.info/lookaround.html говорит об этом. Есть ли другие хорошие учебники? - person aradhak; 11.06.2012
comment
@ Кэтрин, да, читай этот сайт (у меня есть). Следует помнить, что поиск не соответствует вашему результату, поэтому просто проверьте. - person dacwe; 11.06.2012

Мне кажется, что большая часть вашего стресса связана с необходимостью избегать специальных символов в вашем поисковом запросе. Я настоятельно рекомендую не экранировать специальные символы вручную, а вместо этого использовать Pattern.quote(...) для экранирования.

person Bananeweizen    schedule 11.06.2012

Это должно работать

 "(?<=\\))::|::(?=\\()"
person chaitu    schedule 11.06.2012

Это должно сработать для вас.

\)::|::\(
person Adam Merrifield    schedule 11.06.2012

textString.split("\\)::|::\\(") 

должно сработать.

person MoveFast    schedule 11.06.2012
comment
обратная косая черта появляется дважды... не знаю, почему форматирование удаляет мою вторую обратную косую черту - person MoveFast; 11.06.2012
comment
Если форматирование мешает вашему коду, сделайте его блоком кода или используйте ` ` ` эти like this - person dantuch; 11.06.2012
comment
Он не будет включать ) в первой строке и ( в 3-й строке - person Chandra Sekhar; 11.06.2012
comment
Спасибо за ответ. Я отказался от синтаксического анализа, так как строка оказалась слишком сложной. Но, как предположила Чандра Секхар, он пропустил ( из первой строки и ) из последней строки. Это хорошая идея заменить :: на )):: и ::( на ::(( перед синтаксическим анализом? - person aradhak; 11.06.2012