Да, вам нужно отрицание. Регулярное выражение будет [^\p{L}]
для всего, кроме букв . Другой способ написать это будет \P{L}
.
\p{M}
означает «все знаки», поэтому [^\p{L}\p{M}]
означает ** все, что не является ни буквой, ни знаком. Это также можно записать как [\P{L}&&[\P{M}]]
, но на самом деле это не лучше.
В строке Java все \
должны быть удвоены, поэтому вы должны написать string.replaceAll("[^\\p{L}\\p{M}]", "replacement")
.
Из комментария:
Кстати, относительно вашего ответа, что попадает в категорию оценок? Мне это вообще нужно?
Разве буквы не подходят для имени?
Эта категория состоит из подкатегорий
Mn: Марк, без пробелов
Примером этого является ̀
, U + 0300. Это АКЦЕНТ КОМБИНИРОВАННОЙ МОГИЛКИ, и его можно использовать вместе с буквой (буквой перед) для создания акцентированных символов. Для часто используемых акцентированных символов уже есть предварительно составленная форма (например, é
), но для других - нет.
Mc: Mark, Spacing Combining.
Это довольно редко ... Я нашел их в основном в южно-азиатских сценариях и для музыкальных нот. Например, у нас есть U + 1D165, СТРОКА СОЧЕТАНИЯ МУЗЫКАЛЬНОГО СИМВОЛА. 텦, который можно сочетать с U + 1D15D, МУЗЫКАЛЬНЫЙ СИМВОЛ ВСЕ ПРИМЕЧАНИЕ, 텝, к чему-то вроде 텝텦. (Хм, изображения здесь выглядят не так. Полагаю, мой браузер не поддерживает эти символы. Посмотрите на кодовые таблицы , если они здесь не правы.)
Я: Марк, вмещающий
Это отметки, которые каким-то образом заключают в себе основную букву (предыдущую, если я правильно понимаю). Одним из примеров будет U + 20DD, ⃝, который позволяет создавать такие вещи, как A⃝
. (Это должно быть отображено как A, заключенный в кружок, если я правильно понимаю. В моем браузере это не так.) Другим будет U + 20E3, ⃣, КОМБИНИРУЮЩАЯ ЗАКРЫТИЯ KEYCAP, которая должна выглядеть как крышка ключа с буквой (A (). (Они не отображаются в моем браузере. Посмотрите кодовую диаграмму , если вы их не видите.)
Вы можете найти их все, выполнив поиск в Unicode-Data.txt для ;Mn;
, ;Mc;
или ;Me;
, соответственно. Некоторая дополнительная информация содержится в FAQ: символы и сочетания знаков .
Они вам нужны? Я не уверен здесь. Я думаю, что наиболее распространенные имена (по крайней мере, в латинских алфавитах) используют предварительно составленные буквы. Но пользователь может вводить их в разложенном виде - я думаю, что в Mac OS X это по умолчанию. Вам придется запустить алгоритм нормализации, прежде чем отфильтровывать неизвестные символы. (Запуск нормализации в любом случае кажется хорошей идеей, если вы хотите сравнить имена, а не только показать их на экране.)
Редактировать: не имеет прямого отношения к вопросу, но относится к обсуждению в комментариях:
Я написал программу быстрого тестирования, чтобы показать, что [^\pL\pM]
не эквивалентно [\PL\PM]
:
package de.fencing_game.paul.examples;
import java.util.regex.*;
public class RegexSample {
static String[] regexps = {
"[^\\pL\\pM]", "[\\PL\\PM]",
".", "\\pL", "\\pM",
"\\PL", "\\PM"
};
static String[] strings = {
"x", "A", "3", "\n", ".", "\t", "\r", "\f",
" ", "-", "!", "»", "›", "‹", "«",
"ͳ", "Θ", "Σ", "Ϫ", "Ж", "ؤ",
"༬", "༺", "༼", "ང", "⃓", "✄",
"⟪", "や", "゙",
"+", "→", "∑", "∢", "※", "⁉", "⧓", "⧻",
"⑪", "⒄", "⒰", "ⓛ", "⓶",
"\u0300" /* COMBINING GRAVE ACCENT, Mn */,
"\u0BCD" /* TAMIL SIGN VIRAMA, Me */,
"\u20DD" /* COMBINING ENCLOSING CIRCLE, Me */,
"\u2166" /* ROMAN NUMERAL SEVEN, Nl */,
};
public static void main(String[] params) {
Pattern[] patterns = new Pattern[regexps.length];
System.out.print(" ");
for(int i = 0; i < regexps.length; i++) {
patterns[i] = Pattern.compile(regexps[i]);
System.out.print("| " + patterns[i] + " ");
}
System.out.println();
System.out.print("-------");
for(int i = 0; i < regexps.length; i++) {
System.out.print("|-" +
"--------------".substring(0,
regexps[i].length()) +
"-");
}
System.out.println();
for(int j = 0; j < strings.length; j++) {
System.out.printf("U+%04x ", (int)strings[j].charAt(0));
for(int i = 0; i < regexps.length; i++) {
boolean match = patterns[i].matcher(strings[j]).matches();
System.out.print("| " + (match ? "✔" : "-") +
" ".substring(0, regexps[i].length()));
}
System.out.println();
}
}
}
Вот вывод (с OpenJDK 1.6.0_20 на OpenSUSE):
| [^\pL\pM] | [\PL\PM] | . | \pL | \pM | \PL | \PM
-------|-----------|----------|---|-----|-----|-----|-----
U+0078 | - | ✔ | ✔ | ✔ | - | - | ✔
U+0041 | - | ✔ | ✔ | ✔ | - | - | ✔
U+0033 | ✔ | ✔ | ✔ | - | - | ✔ | ✔
U+000a | ✔ | ✔ | - | - | - | ✔ | ✔
U+002e | ✔ | ✔ | ✔ | - | - | ✔ | ✔
U+0009 | ✔ | ✔ | ✔ | - | - | ✔ | ✔
U+000d | ✔ | ✔ | - | - | - | ✔ | ✔
U+000c | ✔ | ✔ | ✔ | - | - | ✔ | ✔
U+0020 | ✔ | ✔ | ✔ | - | - | ✔ | ✔
U+002d | ✔ | ✔ | ✔ | - | - | ✔ | ✔
U+0021 | ✔ | ✔ | ✔ | - | - | ✔ | ✔
U+00bb | ✔ | ✔ | ✔ | - | - | ✔ | ✔
U+203a | ✔ | ✔ | ✔ | - | - | ✔ | ✔
U+2039 | ✔ | ✔ | ✔ | - | - | ✔ | ✔
U+00ab | ✔ | ✔ | ✔ | - | - | ✔ | ✔
U+0373 | ✔ | ✔ | ✔ | - | - | ✔ | ✔
U+0398 | - | ✔ | ✔ | ✔ | - | - | ✔
U+03a3 | - | ✔ | ✔ | ✔ | - | - | ✔
U+03ea | - | ✔ | ✔ | ✔ | - | - | ✔
U+0416 | - | ✔ | ✔ | ✔ | - | - | ✔
U+0624 | - | ✔ | ✔ | ✔ | - | - | ✔
U+0f2c | ✔ | ✔ | ✔ | - | - | ✔ | ✔
U+0f3a | ✔ | ✔ | ✔ | - | - | ✔ | ✔
U+0f3c | ✔ | ✔ | ✔ | - | - | ✔ | ✔
U+0f44 | - | ✔ | ✔ | ✔ | - | - | ✔
U+20d3 | - | ✔ | ✔ | - | ✔ | ✔ | -
U+2704 | ✔ | ✔ | ✔ | - | - | ✔ | ✔
U+27ea | ✔ | ✔ | ✔ | - | - | ✔ | ✔
U+3084 | - | ✔ | ✔ | ✔ | - | - | ✔
U+3099 | - | ✔ | ✔ | - | ✔ | ✔ | -
U+002b | ✔ | ✔ | ✔ | - | - | ✔ | ✔
U+2192 | ✔ | ✔ | ✔ | - | - | ✔ | ✔
U+2211 | ✔ | ✔ | ✔ | - | - | ✔ | ✔
U+2222 | ✔ | ✔ | ✔ | - | - | ✔ | ✔
U+203b | ✔ | ✔ | ✔ | - | - | ✔ | ✔
U+2049 | ✔ | ✔ | ✔ | - | - | ✔ | ✔
U+29d3 | ✔ | ✔ | ✔ | - | - | ✔ | ✔
U+29fb | ✔ | ✔ | ✔ | - | - | ✔ | ✔
U+246a | ✔ | ✔ | ✔ | - | - | ✔ | ✔
U+2484 | ✔ | ✔ | ✔ | - | - | ✔ | ✔
U+24b0 | ✔ | ✔ | ✔ | - | - | ✔ | ✔
U+24db | ✔ | ✔ | ✔ | - | - | ✔ | ✔
U+24f6 | ✔ | ✔ | ✔ | - | - | ✔ | ✔
U+0300 | - | ✔ | ✔ | - | ✔ | ✔ | -
U+0bcd | - | ✔ | ✔ | - | ✔ | ✔ | -
U+20dd | - | ✔ | ✔ | - | ✔ | ✔ | -
U+2166 | ✔ | ✔ | ✔ | - | - | ✔ | ✔
Мы можем видеть, что:
[^\pL\pM]
равно не эквивалентно [\PL\PM]
[\PL\PM]
действительно соответствует всему, но
- still
[\PL\PM]
не равно .
, поскольку .
не соответствует \n
и \r
.
Второй момент вызван тем, что [\PL\PM]
является объединением из \PL
и \PM
: \PL
содержит символы из всех категорий, кроме L (включая M), и \PM
содержит символы из всех категорий, кроме M (включая L) - вместе они содержат весь репертуар символов.
[^pL\pM]
, с другой стороны, является дополнением объединения \pL
и \pM
, что эквивалентно пересечению из \PL
и PM
.