Я подозреваю, что вы после этого:
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 делает.
Редактировать: У вас, кажется, две проблемы:
- \ W потребляет символы из вашего ввода; и
- У вас есть специальные символы регулярных выражений в ваших фразах.
(1) можно обрабатывать несколькими способами. Мой подход выше заключается в использовании \ b вместо этого, поскольку он имеет нулевую ширину и является гораздо лучшим решением. Вы также можете использовать другие утверждения нулевой ширины, такие как lookaheads и lookbehinds:
<?<=\W|^)...(?=\W|$)
но это в основном эквивалентно:
\b...\b
, который гораздо легче читать.
(2) может быть обработано цитированием фраз. Я изменил приведенный выше код для вызова Pattern.quote()
, чтобы заключить в кавычки любые специальные символы регулярного выражения.