Java Regex для регулярного выражения, чтобы удалить двойные дефисы и сохранить одиночные
Поэтому мне нужно регулярное выражение, которое удаляет все несловарные символы (кроме пробелов и дефисов) из текста, чтобы я мог посчитать количество слов в тексте. Что-то вроде
String().replaceAll("[^\\p{L}+(?:\\-\n?\\p{L}+)* ]", "")
в основном работает, так как содержит дефисные слова, но проблема возникает, когда я получаю двойной дефис. Предполагается, что двойной дефис в американском английском представляет одну черточку, поэтому в моем случае мне нужно заменить его пробелом. Кто-нибудь знает, как это изменить, чтобы этого не произошло?
Вот пример. Следующее предложение:
Пока я был вне кампуса, я потерял все свои вещи - кошелек, ключи, все!
Должно выглядеть так после регулярного выражения:
В то время как я был за пределами кампуса, я потерял все свои вещи ключи от кошелька все
РЕДАКТИРОВАТЬ - я не заинтересован в использовании двух replaceAll, я хочу сделать это в одном регулярном выражении.
1 ответ
Ваше оригинальное регулярное выражение нарушено, так как (?:...)
а также *
, +
обрабатываются как буквальный символ внутри класса символов []
,
В классе символов в Java, [
, ]
, \
(для escape-последовательностей и свойств), \Q
, \E
(для цитирования специальных символов в классе символов), ^
(действует только в начале урока), -
(действует от 2 символов), &&
(для пересечения классов символов) являются единственными символами / последовательностями со специальным значением.
Вы можете проверить свое регулярное выражение в этом примере строки, чтобы подтвердить сказанное выше.
Это еще один пример: (скобки) + [скобки] + (звездочки *)
Вместо удаления недопустимых символов и материалов, вы можете просто сопоставить слова непосредственно с этим регулярным выражением (частью внутри класса символов вашего регулярного выражения):
"\\p{L}+(?:-\n?\\p{L}+)*"
Приведенное выше регулярное выражение можно использовать в цикле Matcher для подсчета количества слов:
Pattern p = Pattern.compile("\\p{L}+(?:-\n?\\p{L}+)*");
Matcher m = p.matcher(input);
int count = 0;
while (m.find()) {
count++;
}
Если вы все еще хотите заменить все символы, не соответствующие определению слова, как определено в регулярном выражении выше:
input.replaceAll("(?s).*?(\\p{L}+(?:-\n?\\p{L}+)*)|.+", "$1 ");
(?s).*?(\\p{L}+(?:-\n?\\p{L}+)*)
выполняет поиск не-слова-символов перед словом и удаляет их, а после слова добавляется пробел. .+
в конце имеет дело с последовательностью не-словесных символов в конце строки.
Обратите внимание, что он создаст завершающий пробел, если последний символ не является частью слова.
Тестовый ввод:
While I was off-campus, I lost all my belongings--wallet, keys, everything!
This is another example: (parentheses) + [brackets] + (asterisks *)
Along-
longl-
onglo-
ngword!
Тестовый вывод (обратите внимание на завершающий пробел в конце):
While I was off-campus I lost all my belongings wallet keys everything This is another example parentheses brackets asterisks Along- longl- onglo- ngword
Если вы спросите, могу ли я исключить завершающее пространство, изменив приведенное выше регулярное выражение, я бы сказал, что это невозможно в Java. Проблема здесь в том, что --
должен быть заменен пробелом, чтобы отделить 2 "слова", в то время как другие не "слова" символы должны быть заменены пустой строкой.