为什么这个表情符号正则表达式也匹配数字
why is this emoji regex also matching numerics
我正在编写一个需要从字符串中去除表情符号的程序,发现这个正则表达式似乎删除了我迄今为止测试过的所有表情符号:
private static final String EMOJI_REGEX= "[\u200D(?:"
+ "[\uD83C\uDF00-\uD83D\uDDFF]|"
+ "[\uD83E\uDD00-\uD83E\uDDFF]|"
+ "[\uD83D\uDE00-\uD83D\uDE4F]|"
+ "[\uD83D\uDE80-\uD83D\uDEFF]|"
+ "[\u2600-\u26FF]\uFE0F?|"
+ "[\u2700-\u27BF]\uFE0F?|"
+ "\u24C2\uFE0F?|"
+ "[\uD83C\uDDE6-\uD83C\uDDFF]{1,2}|"
+ "[\uD83C\uDD70\uD83C\uDD71\uD83C\uDD7E\uD83C\uDD7F\uD83C\uDD8E\uD83C\uDD91-\uD83C\uDD9A]\uFE0F?|"
+ "[\u0023\u002A\u0030-\u0039]\uFE0F?\u20E3|[\u2194-\u2199\u21A9-\u21AA]\uFE0F?|"
+ "[\u2B05-\u2B07\u2B1B\u2B1C\u2B50\u2B55]\uFE0F?|"
+ "[\u2934\u2935]\uFE0F?|"
+ "[\u3030\u303D]\uFE0F?|"
+ "[\u3297\u3299]\uFE0F?|"
+ "[\uD83C\uDE01\uD83C\uDE02\uD83C\uDE1A\uD83C\uDE2F\uD83C\uDE32-"
+ "\uD83C\uDE3A\uD83C\uDE50\uD83C\uDE51]\uFE0F?|"
+ "[\u203C\u2049]\uFE0F?|[\u25AA\u25AB\u25B6\u25C0\u25FB-\u25FE]\uFE0F?|[\u00A9\u00AE]\uFE0F?|"
+ "[\u2122\u2139]\uFE0F?|\uD83C\uDC04\uFE0F?|\uD83C\uDCCF\uFE0F?|"
+ "[\u231A\u231B\u2328\u23CF\u23E9-\u23F3\u23F8-\u23FA]\uFE0F?)]";
当我像这样使用这个正则表达式时:
strippedString = regexString.replaceAll(EMOJI_REGEX, "");
它成功删除了所有表情符号。但是,我尝试使用我不想剥离的数据对其进行测试,并且该正则表达式似乎也与数字匹配。例如,当我通过测试字符串 Testing £1.01☂
时,输出为 Testing £.
.
我尝试从上面的正则表达式中删除 \u0030-\u0039
范围,但现在我得到 Testing £.0
.
谁能告诉我这是怎么回事,我该如何解决这个问题?
重要说明 由于古老的体系结构,此问题的解决方案必须符合 java 6。
由于您的正则表达式只是一堆 |
的范围,我们可以编写一些测试代码来查看哪些范围删除了数字:
public class RegexTest
{
private static final String regexbegin = "[\u200D(?:";
private static final String regexend = ")]";
private static final String[] regexparts =
{
"[\uD83C\uDF00-\uD83D\uDDFF]",
"[\uD83E\uDD00-\uD83E\uDDFF]",
"[\uD83D\uDE00-\uD83D\uDE4F]",
"[\uD83D\uDE80-\uD83D\uDEFF]",
"[\u2600-\u26FF]\uFE0F?",
"[\u2700-\u27BF]\uFE0F?",
"\u24C2\uFE0F?",
"[\uD83C\uDDE6-\uD83C\uDDFF]{1,2}",
"[\uD83C\uDD70\uD83C\uDD71\uD83C\uDD7E\uD83C\uDD7F\uD83C\uDD8E\uD83C\uDD91-\uD83C\uDD9A]\uFE0F?",
"[\u0023\u002A\u0030-\u0039]\uFE0F?\u20E3",
"[\u2194-\u2199\u21A9-\u21AA]\uFE0F?",
"[\u2B05-\u2B07\u2B1B\u2B1C\u2B50\u2B55]\uFE0F?",
"[\u2934\u2935]\uFE0F?",
"[\u3030\u303D]\uFE0F?",
"[\u3297\u3299]\uFE0F?",
"[\uD83C\uDE01\uD83C\uDE02\uD83C\uDE1A\uD83C\uDE2F\uD83C\uDE32-\uD83C\uDE3A\uD83C\uDE50\uD83C\uDE51]\uFE0F?",
"[\u203C\u2049]\uFE0F?",
"[\u25AA\u25AB\u25B6\u25C0\u25FB-\u25FE]\uFE0F?",
"[\u00A9\u00AE]\uFE0F?",
"[\u2122\u2139]\uFE0F?",
"\uD83C\uDC04\uFE0F?",
"\uD83C\uDCCF\uFE0F?",
"[\u231A\u231B\u2328\u23CF\u23E9-\u23F3\u23F8-\u23FA]\uFE0F?",
};
public static void main(final String[] args)
{
final String test = "Testing £1.01☂";
for (int i = 0; i < regexparts.length; i++) {
final String regex = regexbegin + regexparts[i] + regexend;
System.out.println(i + ": " + test.replaceAll(regex, ""));
}
}
}
使用这段代码我们得到:
0: Testing £1.01☂
1: Testing £1.01☂
2: Testing £1.01☂
3: Testing £1.01☂
4: Testing £1.01
5: Testing £1.01☂
6: Testing £1.01☂
7: Testing £.0☂
8: Testing £1.01☂
9: Testing £.☂
10: Testing £1.01☂
11: Testing £1.01☂
12: Testing £1.01☂
13: Testing £1.01☂
14: Testing £1.01☂
15: Testing £1.01☂
16: Testing £1.01☂
17: Testing £1.01☂
18: Testing £1.01☂
19: Testing £1.01☂
20: Testing £1.01☂
21: Testing £1.01☂
22: Testing £1.01☂
所以索引 7
和索引 9
处的范围是你的罪魁祸首:
"[\uD83C\uDDE6-\uD83C\uDDFF]{1,2}"
"[\u0023\u002A\u0030-\u0039]\uFE0F?\u20E3"
直接在数字上使用这些仅测试 String
System.out.println("7: " + "0123456789".replaceAll(regexbegin + regexparts[7] + regexend, ""));
System.out.println("9: " + "0123456789".replaceAll(regexbegin + regexparts[9] + regexend, ""));
产生这个:
7: 03456789
9:
前者去掉1和2,后者去掉所有数字
Max Vollmer 已经回答,但想知道为什么
[\u0023\u002A\u0030-\u0039]\uFE0F?\u20E3
匹配号码,见Emoji Keyboard/Display Test Data
如您所见,[\u0030-\u0039]\uFE0F?\u20E3
匹配键帽范围 0 到 9(请参阅子组:键帽)。
至于
[\uD83C\uDDE6-\uD83C\uDDFF]{1,2}
删除范围 {1,2}
应该有效。
我正在编写一个需要从字符串中去除表情符号的程序,发现这个正则表达式似乎删除了我迄今为止测试过的所有表情符号:
private static final String EMOJI_REGEX= "[\u200D(?:"
+ "[\uD83C\uDF00-\uD83D\uDDFF]|"
+ "[\uD83E\uDD00-\uD83E\uDDFF]|"
+ "[\uD83D\uDE00-\uD83D\uDE4F]|"
+ "[\uD83D\uDE80-\uD83D\uDEFF]|"
+ "[\u2600-\u26FF]\uFE0F?|"
+ "[\u2700-\u27BF]\uFE0F?|"
+ "\u24C2\uFE0F?|"
+ "[\uD83C\uDDE6-\uD83C\uDDFF]{1,2}|"
+ "[\uD83C\uDD70\uD83C\uDD71\uD83C\uDD7E\uD83C\uDD7F\uD83C\uDD8E\uD83C\uDD91-\uD83C\uDD9A]\uFE0F?|"
+ "[\u0023\u002A\u0030-\u0039]\uFE0F?\u20E3|[\u2194-\u2199\u21A9-\u21AA]\uFE0F?|"
+ "[\u2B05-\u2B07\u2B1B\u2B1C\u2B50\u2B55]\uFE0F?|"
+ "[\u2934\u2935]\uFE0F?|"
+ "[\u3030\u303D]\uFE0F?|"
+ "[\u3297\u3299]\uFE0F?|"
+ "[\uD83C\uDE01\uD83C\uDE02\uD83C\uDE1A\uD83C\uDE2F\uD83C\uDE32-"
+ "\uD83C\uDE3A\uD83C\uDE50\uD83C\uDE51]\uFE0F?|"
+ "[\u203C\u2049]\uFE0F?|[\u25AA\u25AB\u25B6\u25C0\u25FB-\u25FE]\uFE0F?|[\u00A9\u00AE]\uFE0F?|"
+ "[\u2122\u2139]\uFE0F?|\uD83C\uDC04\uFE0F?|\uD83C\uDCCF\uFE0F?|"
+ "[\u231A\u231B\u2328\u23CF\u23E9-\u23F3\u23F8-\u23FA]\uFE0F?)]";
当我像这样使用这个正则表达式时:
strippedString = regexString.replaceAll(EMOJI_REGEX, "");
它成功删除了所有表情符号。但是,我尝试使用我不想剥离的数据对其进行测试,并且该正则表达式似乎也与数字匹配。例如,当我通过测试字符串 Testing £1.01☂
时,输出为 Testing £.
.
我尝试从上面的正则表达式中删除 \u0030-\u0039
范围,但现在我得到 Testing £.0
.
谁能告诉我这是怎么回事,我该如何解决这个问题?
重要说明 由于古老的体系结构,此问题的解决方案必须符合 java 6。
由于您的正则表达式只是一堆 |
的范围,我们可以编写一些测试代码来查看哪些范围删除了数字:
public class RegexTest
{
private static final String regexbegin = "[\u200D(?:";
private static final String regexend = ")]";
private static final String[] regexparts =
{
"[\uD83C\uDF00-\uD83D\uDDFF]",
"[\uD83E\uDD00-\uD83E\uDDFF]",
"[\uD83D\uDE00-\uD83D\uDE4F]",
"[\uD83D\uDE80-\uD83D\uDEFF]",
"[\u2600-\u26FF]\uFE0F?",
"[\u2700-\u27BF]\uFE0F?",
"\u24C2\uFE0F?",
"[\uD83C\uDDE6-\uD83C\uDDFF]{1,2}",
"[\uD83C\uDD70\uD83C\uDD71\uD83C\uDD7E\uD83C\uDD7F\uD83C\uDD8E\uD83C\uDD91-\uD83C\uDD9A]\uFE0F?",
"[\u0023\u002A\u0030-\u0039]\uFE0F?\u20E3",
"[\u2194-\u2199\u21A9-\u21AA]\uFE0F?",
"[\u2B05-\u2B07\u2B1B\u2B1C\u2B50\u2B55]\uFE0F?",
"[\u2934\u2935]\uFE0F?",
"[\u3030\u303D]\uFE0F?",
"[\u3297\u3299]\uFE0F?",
"[\uD83C\uDE01\uD83C\uDE02\uD83C\uDE1A\uD83C\uDE2F\uD83C\uDE32-\uD83C\uDE3A\uD83C\uDE50\uD83C\uDE51]\uFE0F?",
"[\u203C\u2049]\uFE0F?",
"[\u25AA\u25AB\u25B6\u25C0\u25FB-\u25FE]\uFE0F?",
"[\u00A9\u00AE]\uFE0F?",
"[\u2122\u2139]\uFE0F?",
"\uD83C\uDC04\uFE0F?",
"\uD83C\uDCCF\uFE0F?",
"[\u231A\u231B\u2328\u23CF\u23E9-\u23F3\u23F8-\u23FA]\uFE0F?",
};
public static void main(final String[] args)
{
final String test = "Testing £1.01☂";
for (int i = 0; i < regexparts.length; i++) {
final String regex = regexbegin + regexparts[i] + regexend;
System.out.println(i + ": " + test.replaceAll(regex, ""));
}
}
}
使用这段代码我们得到:
0: Testing £1.01☂
1: Testing £1.01☂
2: Testing £1.01☂
3: Testing £1.01☂
4: Testing £1.01
5: Testing £1.01☂
6: Testing £1.01☂
7: Testing £.0☂
8: Testing £1.01☂
9: Testing £.☂
10: Testing £1.01☂
11: Testing £1.01☂
12: Testing £1.01☂
13: Testing £1.01☂
14: Testing £1.01☂
15: Testing £1.01☂
16: Testing £1.01☂
17: Testing £1.01☂
18: Testing £1.01☂
19: Testing £1.01☂
20: Testing £1.01☂
21: Testing £1.01☂
22: Testing £1.01☂
所以索引 7
和索引 9
处的范围是你的罪魁祸首:
"[\uD83C\uDDE6-\uD83C\uDDFF]{1,2}"
"[\u0023\u002A\u0030-\u0039]\uFE0F?\u20E3"
直接在数字上使用这些仅测试 String
System.out.println("7: " + "0123456789".replaceAll(regexbegin + regexparts[7] + regexend, ""));
System.out.println("9: " + "0123456789".replaceAll(regexbegin + regexparts[9] + regexend, ""));
产生这个:
7: 03456789
9:
前者去掉1和2,后者去掉所有数字
Max Vollmer 已经回答,但想知道为什么
[\u0023\u002A\u0030-\u0039]\uFE0F?\u20E3
匹配号码,见Emoji Keyboard/Display Test Data
如您所见,[\u0030-\u0039]\uFE0F?\u20E3
匹配键帽范围 0 到 9(请参阅子组:键帽)。
至于
[\uD83C\uDDE6-\uD83C\uDDFF]{1,2}
删除范围 {1,2}
应该有效。