Rih*_*rds 4 java regex unicode character-properties
我需要编写一个正则表达式,这样我就可以在进一步发送之前替换用户输入中的无效字符.我想我需要string.replaceAll("regex", "replacement")用来做那件事.特定的代码行应该替换所有不是unicode字母的字符.所以这是一个unicode字符的白名单.基本上它正在验证并替换用户名字的无效字符.
到目前为止我发现的是:\p{L}\p{M}但是我不确定如何在regexp中启动它,所以它会像我上面解释的那样工作.这会是一个正则表达式否定的情况吗?
是的,你需要否定.正则表达式将[^\p{L}]用于除字母之外的任何内容.写这个的另一种方法是\P{L}.
\p{M}意思是"所有标记",因此[^\p{L}\p{M}]意味着**任何既不是字母也不标记的东西.这也可以写成[\P{L}&&[\P{M}]],但这并不是更好.
在Java-String中,所有\都必须加倍,所以你可以string.replaceAll("[^\\p{L}\\p{M}]", "replacement")在那里写.
来自评论:
顺便说一下,关于你的回答,什么属于商标类别?我甚至需要吗?不仅仅是字母对名字没问题吗?
此类别包含子类别
Mn:标记,非间距
例如?,U + 0300.这是COMBINING GRAVE ACCENT,可与字母(前面的字母)一起使用来创建重音字符.对于常用的重音字符,已经存在预组合形式(例如é),但对于其他形式则没有.
麦克:马克,间距组合.
这些很少......我发现它们主要是南亚文字和音符.例如,我们有U + 1D165,MUSICAL SYMBOL COMBINING STEM.텦,可以与U + 1D15D,MUSICAL SYMBOL WHOLE NOTE,combined组合,类似于텝텦.(嗯,这些图像看起来不对.我想我的浏览器不支持这些字符.看看代码图表,如果它们在这里错了.)
我:马克,附上
这些标记以某种方式包含基本字母(前一个,如果我理解的话).一个例子是U + 20DD,⃝,它允许创建类似的东西A?.(如果我理解的话,这应该被呈现为圆圈所包围的A.在我的浏览器中它不会.)另一个是U + 20E3,⃣,COMBINING ENCLOSING KEYCAP,它应该给出一个关键帽的外观随信(A⃣).(它们不会显示在我的浏览器中.如果您看不到它们,请查看代码表.)
您可以通过所有搜索中找到他们Unicode的DATA.TXT的;Mn;,;Mc;或;Me;分别.常见问题解答中包含更多信息:字符和组合标记.
你需要它们吗?我不确定.我认为,最常见的名字(至少在拉丁字母表中)会使用预先组合的字母.但是用户可能会以分解的形式输入它们 - 我认为在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();
}
}
}
Run Code Online (Sandbox Code Playgroud)
这是输出(在OpenSUSE上使用OpenJDK 1.6.0_20):
| [^\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 | ? | ? | ? | - | - | ? | ?
Run Code Online (Sandbox Code Playgroud)
我们可以看到:
[^\pL\pM]是不是等同于[\PL\PM][\PL\PM] 真的匹配一切,但是[\PL\PM]不等于.,因为.不匹配\n和\r.第二点是由以下事实引起的[\PL\PM]是联合的\PL和\PM:\PL含有比L(包括M)之外的所有类别的字符,并\PM含有来自除M(包括L)以外的所有类别的字符-它们一起包含整个字符集.
[^pL\pM],在另一方面,是的并集的补集\pL和\pM,这等同于交叉点的\PL和PM.