2012-03-15 3 views
7

Я хочу построить регулярное выражение, которое соответствует либо ', либо ", а затем соответствует другим символам, заканчивающимся, когда сопоставлены ' или ", в зависимости от того, начало. Таким образом, эта проблема кажется достаточно простой, чтобы решить с использованием обратной ссылки в конце; вот некоторые регулярное выражение ниже код (это в Java, так возражаете дополнительные символы побега, такие как \ перед "):Regex; обратное обращение к символу, который НЕ был сопоставлен в наборе символов

private static String seekerTwo = "(['\"])([a-zA-Z])([a-zA-Z0-9():;/`\\=\\.\\,\\- ]+)(\\1)"; 

Этот код будет успешно справляться с вещами, такими как:

"hello my name is bob" 
'i live in bethnal green' 

Проблема возникает, когда у меня есть строки вроде этого:

"hello this seat 'may be taken' already" 

Использования выше регулярного выражения на нем не удастся на начальном участке при встрече ', то он будет продолжать и успешно соответствовать 'may be taken' ... но этого явно недостаточно, мне нужно, чтобы вся строка была согласована.

Я думаю, что мне нужен способ игнорировать тип кавычки, который НЕ был сопоставлен в первой группе, включив его в качестве символа в наборе символов третьей группы. Однако я не знаю, как это сделать. Есть ли какая-то скрытая функция NOT backreference или что-то в этом роде? Что-то, что я могу использовать для ссылки на символ в 1-й группе, которая НЕ была сопоставлена ​​?? Или иначе какое-то решение моего затруднительного положения?

+0

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

ответ

12

Это можно сделать, используя отрицательный lookahead assertions. Следующее решение даже принимает во внимание, что вы могли бы избежать цитата внутри строки:

(["'])(?:\\.|(?!\1).)*\1 

Пояснение:

(["']) # Match and remember a quote. 
(?:  # Either match... 
\\.  # an escaped character 
|   # or 
(?!\1) # (unless that character is identical to the quote character in \1) 
.  # any character 
)*  # any number of times. 
\1  # Match the corresponding quote. 

Это правильно соответствует "hello this seat 'may be taken' already" или "hello this seat \"may be taken\" already".

В Java, со всеми обратной косой черты:

Pattern regex = Pattern.compile(
    "([\"']) # Match and remember a quote.\n" + 
    "(?:  # Either match...\n" + 
    " \\\\. # an escaped character\n" + 
    "|   # or\n" + 
    " (?!\\1) # (unless that character is identical to the matched quote char)\n" + 
    " .  # any character\n" + 
    ")*  # any number of times.\n" + 
    "\\1  # Match the corresponding quote", 
    Pattern.COMMENTS); 
+0

+1 для хорошо продуманного и объясненного решения! – FloppyDisk

+0

Отличная работа там Тим, и спасибо за редактирование моего сообщения. Благодаря вашему предложению я немного изменил свой код: «(['\"]) ([a-zA-Z]) ((?! \\ 1) [a-zA-Z0-9():;/''\" \\ = \\. \\, \\ -]) + (\\ 1) ", поэтому ваше решение было фактически достаточно простым и совершенно эффективным; добавьте равновероятность регулярного выражения, если статут перед основным набором символов, который пропустит право на последний цикл. И добавьте оба типа кавычек в основной набор символов. Таким образом, если найденный символ цитаты с открытым исходным кодом найден в любое время, регулярное выражение завершится и вернется. Ницца. –

2

решение Тима работает довольно хорошо, если вы можете использовать lookaround (что Java не поддерживает). Но если вы должны найти себя, используя язык или инструмент, который не поддерживает lookaround, вы могли бы просто соответствовать оба случая (двойные кавычки строки и отдельные строки в кавычках) отдельно:

"(\\"|[^"])*"|'(\\'|[^'])*' 

матчи каждый случай отдельно, но возвращает либо случай как весь матч


ОДНАКО

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

Он повернулся, чтобы получить на свой велосипед.«Увидимся позже, когда со мной все закончится», - сказал он, оглядываясь на мгновение, прежде чем отправиться в путь. Когда он вошел на улицу, одна из городских тележек столкнулась с велосипедом Майка. «О, мой!» - воскликнул зритель.

... но есть три матчи, не два:

"I'll see you later, when I'm done with all this" 
's trolleys collided with Mike' 
"Oh my!" 

и этот отрывок содержит только ONE матч:

Борьба была не закончена , хоть. "Привет!" - закричал Боб. "Что ты хочешь?" - возразил я. «Я ненавижу твою кишку!» «Почему меня это волнует?» "Потому что я тебя люблю!" "Вы делаете?" Боб несколько секунд остановился, прежде чем прошептал: «Нет, я не мог тебя любить!»

вы можете найти это? : D

't over yet, though. "Hey!" yelled Bob. "What do you want?" I retorted. "I hate your guts!" "Why would I care?" "Because I love you!" "You do?" Bob paused for a moment before whispering "No, I couldn' 

Я бы рекомендовал (если вы за помощью lookaround), что вы выполнить некоторые дополнительные проверки (например, положительные назад 'для пробельного или подобных до появления первой котировки), чтобы убедиться, что вы не» t соответствует таким вещам, как 's trolleys collided with Mike' - хотя я бы не стал вкладывать много денег в любое решение без большого тестирования. Добавление (?<=\s|^) к началу либо выражения будет избежать вышеуказанных случаев ... то есть:

(?<=\s|^)(["'])(?:\\.|(?!\1).)*\1     #based on Tim's 

или

(?<=\s|^)("(\\"|[^"])*"|'(\\'|[^'])*')    #based on my alternative 

Я не уверен, насколько эффективно lookaround по сравнению с не-lookaround, так два выше могут быть эквивалентными, или один может быть более эффективным, чем другой (?)

+0

Некоторые хорошие моменты здесь Code Jockey, и, действительно, анализ английского текста таким образом не был бы разумным. Тем не менее, я на самом деле пытаюсь разобрать русский текст в MySQL-коде (я изменил а-яА-Яё на a-zA-Z в моем коде выше, чтобы люди здесь могли понять смысл), и при анализе строк в коде они, конечно же, всегда гарантируются одним типом кавычки или другим. –

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

  • Нет связанных вопросов^_^