использование функции разделителя сканера для «abc-def»
-
09-09-2019 - |
Вопрос
В настоящее время я пытаюсь отфильтровать текстовый файл, содержащий слова, разделенные знаком «-».Я хочу посчитать слова.
scanner.useDelimiter(("[.,:;()?!\" \t\n\r]+"));
Проблема, которая возникает просто:слова, содержащие «-», будут разделены и засчитаны как два слова.Так что просто побег с помощью \- не является лучшим решением.
Как я могу изменить выражение-разделитель, чтобы такие слова, как «foo-bar», остались, но один только «-» будет отфильтрован и проигнорирован?
Спасибо ;)
Решение
Хорошо, я угадываю ваш вопрос здесь:вы имеете в виду, что у вас есть текстовый файл с какой-то "настоящей" прозой, т.е.предложения, которые действительно имеют смысл, разделены знаками препинания и тому подобным и т. д., верно?
Пример:
Насколько мы можем судить, эта ситуация улучшается тем фактом, что наши самые надежные союзники, воргоны, продолжают проводить свои поэтические конкурсы;у врага мало стимулов вмешиваться в это, даже с помощью своих устройств Mute-O-Matic.
Итак, в качестве разделителя вам нужно либо любое количество пробелов и/или знаков препинания (которые вы уже покрыли показанным регулярным выражением), либо дефис, окруженный хотя бы одним пробелом с каждой стороны.Символом регулярного выражения для «или» является «|».Во многих реализациях регулярных выражений существует ярлык для класса символов пробелов (пробелов, табуляции и новой строки):"\с".
"[.,:;()?!\"\s]+|\s+-\s+"
Другие советы
Если возможно, попробуйте использовать предопределенные классы...делает регулярное выражение намного проще для чтения.См. параметры java.util.regex.Pattern.
Возможно, это то, что вы ищете:
string.split("\\s+(\\W*\\s)?"
Читает:Сопоставьте 1 или несколько символов пробела, за которыми (не обязательно) следует ноль или более символов, не являющихся словами, и символ пробела.
Это не очень просто.Можно попробовать следующее: {current-delimeter-chars}{ноль-или-более-дефисов}{ноль-или-более-текущий-делитель-символов-или-дефис}.
Возможно, было бы проще просто игнорировать слова, возвращаемые сканером, состоящие полностью из дефисов.
Scanner scanner = new Scanner("one two2 - (three) four-five - ,....|");
scanner.useDelimiter("(\\B+-\\B+|[.,:;()?!\" \t|])+");
while (scanner.hasNext()) {
System.out.println(scanner.next("\\w+(-\\w+)*"));
}
Примечание:
метод next(String) утверждает, что вы получаете только слова, поскольку исходный метод useDelimiter() пропускает "|"
Примечание:
вы использовали регулярное выражение « | » в качестве признака конца строки.В документации JavaDocs для java.util.regex.Pattern показаны другие возможные символы завершения строки, поэтому для более полной проверки будет использоваться выражение " |[ \u2028\u2029\u0085]"
Это должно быть достаточно просто: [^\\w-]\\W*|-\\W+
- Но конечно если это проза и вы хотите исключить подчеркивает:
[^\\p{Alnum}-]\\P{Alnum}*|-\\P{Alnum}+
- или если вы не ожидаете цифр:
[^\\p{Alpha}-]\\P{Alpha}*|-\\P{Alpha}+
РЕДАКТИРОВАТЬ: Это более простые формы.Имейте в виду, что полное решение, которое будет обрабатывать тире в начале и конце строк, будет следовать этому шаблону. (?:^|[^\\w-])\\W*|-(?:\\W+|$)