Получение фрагментов диалога из текста с использованием регулярных выражений - PullRequest
1 голос
/ 01 июня 2010

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

"What's the matter with the flag?" inquired Captain MacWhirr. "Seems all right to me."

Тогда я хочу извлечь "What's the matter with the flag?" и "Seem's all right to me.".

Я нашел регулярное выражение для использования здесь , то есть "[^"\\]*(\\.[^"\\]*)*". Это прекрасно работает в Eclipse, когда я выполняю регулярное выражение Ctrl + F в файле моей книги .txt, но когда запускаю следующий код:

String regex = "\"[^\"\\\\]*(\\\\.[^\"\\\\]*)*\"";
String bookText = "\"What's the matter with the flag?\" inquired Captain MacWhirr. \"Seems all right to me.\""; Pattern p = Pattern.compile(regex);
Matcher m = p.matcher(bookText);

if(m.find())
 System.out.println(m.group(1));

Единственное, что печатает, это null. Так что я не преобразовываю регулярное выражение в строку Java правильно? Нужно ли принимать во внимание тот факт, что строки Java имеют \" для двойных кавычек?

1 Ответ

5 голосов
/ 01 июня 2010

В тексте на естественном языке маловероятно, что " экранируется предыдущей косой чертой, поэтому вы можете использовать только шаблон "([^"]*)".

Как строковый литерал Java, это "\"([^\"]*)\"".

Вот это на Java:

String regex = "\"([^\"]*)\"";
String bookText = "\"What's the matter with the flag?\" inquired Captain MacWhirr. \"Seems all right to me.\"";
Pattern p = Pattern.compile(regex);
Matcher m = p.matcher(bookText);

while (m.find()) {
    System.out.println(m.group(1));
}

Указанные выше отпечатки:

What's the matter with the flag?
Seems all right to me.

На escape-последовательностях

Учитывая это объявление:

String s = "\"";
System.out.println(s.length()); // prints "1"

Строка s имеет только один символ, ". \ является escape-последовательностью, присутствующей на уровне исходного кода Java; Сама строка не имеет косой черты.

Смотри также


Проблема с оригинальным кодом

На самом деле нет ничего плохого в самом шаблоне, но вы не захватываете правильную часть. \1 не захватывает цитируемый текст. Вот шаблон с правильной группой захвата:

String regex = "\"([^\"\\\\]*(?:\\\\.[^\"\\\\]*)*)\"";
String bookText = "\"What's the matter?\" inquired Captain MacWhirr. \"Seems all right to me.\"";
Pattern p = Pattern.compile(regex);
Matcher m = p.matcher(bookText);

while (m.find()) {
    System.out.println(m.group(1));
}

Для визуального сравнения вот оригинальный шаблон в виде строкового литерала Java:

String regex = "\"[^\"\\\\]*(\\\\.[^\"\\\\]*)*\""
                            ^^^^^^^^^^^^^^^^^
                           why capture this part?

А вот модифицированный шаблон:

String regex = "\"([^\"\\\\]*(?:\\\\.[^\"\\\\]*)*)\""
                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
                    we want to capture this part!

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

Смотри также

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...