Java регулярное выражение логическое ИЛИ - PullRequest
0 голосов
/ 06 января 2010

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

(^|\\W)(" + phrase1 + "|" + phrase2 + "|" + phrase3 + ... ")(\\W|$)

Мне нужно соответствовать любому количеству фраз, которые я OR использую. Кажется, все работает хорошо, за исключением случаев, когда две фразы встречаются непосредственно рядом друг с другом. Таким образом, "phrase1 lorem ipsum phrase2 lorem ipsum" соответствует фразе1 и фразе2, а "phrase1 phrase2 lorem ipsum" соответствует только фразе1 (как и "phrase1.phrase2 lorem ipsum") Если между фразу 1 и фразу 2 имеется более одного несловесного символа (например, два или более пробелов), то он также соответствует обоим. Что я делаю не так?

Ответы [ 2 ]

1 голос
/ 06 января 2010

Я подозреваю, что вы после этого:

List<String> findPhrases(String s, String... phrases) {
  return findPhrases(s, Arrays.asList(phrases));
}

List<String> findPhrases(String s, Collection<String> phrases) {
  if (phrases.size() < 1) {
    throw new IllegalArgumentException("must specify at least one phrase");
  }
  StringBuilder sb = new StringBuilder();
  Iterator<String> iter = phrases.iterator();
  String first = iter.next();
  sb.append(first);
  while (iter.hasNext()) {
    sb.append("|");
    sb.append(iter.next());
  }
  Pattern p = Pattern.compile("\\b(" + sb.toString() + ")\\b");
  Matcher m = p.matcher(s);
  List<String> ret = new ArrayList<String>();
  while (m.find()) {
    ret.append(Pattern.quote(m.group(1)));
  }
  return ret;
}

Одно важное отличие состоит в том, что я использовал \ b вместо \ W для разделения слов. \ b соответствует совпадению нулевой ширины с началом строки, концом строки или переходом от символа слова к символу, отличному от слова, и наоборот.

Zero-width означает, что он не потребляет символ из ввода, как \ W делает.

Редактировать: У вас, кажется, две проблемы:

  1. \ W потребляет символы из вашего ввода; и
  2. У вас есть специальные символы регулярных выражений в ваших фразах.

(1) можно обрабатывать несколькими способами. Мой подход выше заключается в использовании \ b вместо этого, поскольку он имеет нулевую ширину и является гораздо лучшим решением. Вы также можете использовать другие утверждения нулевой ширины, такие как lookaheads и lookbehinds:

<?<=\W|^)...(?=\W|$)

но это в основном эквивалентно:

\b...\b

, который гораздо легче читать.

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

1 голос
/ 06 января 2010

Это потому, что у вас есть \\W по обе стороны от вашего регулярного выражения. То есть первый несловесный символ сопоставляется с первым соответствием, затем второе сопоставление требует еще одного несловесного символа.

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