我有一些字符串,里面有各种不同的表情符号/图像/符号.
并非所有字符串都是英文的 - 其中一些字符串是其他非拉丁语言,例如:
? railway??
? Cats and dogs
I'm on
Apples ?
? Vi sign
? I'm the king ?
Corée ? du Nord ? (French)
gjør at både ?? (Norwegian)
Star me ?
Star ? once more
??? ? (Chinese)
???????? ? (Greek)
another ? sign ?
?????? ?????? ? (Belarus)
? ??? ?????? ? (Hindi)
? ? ? ? Let's get together ?. We shall meet at 12/10/2018 10:00 AM at Tony's.?
......还有更多这些.
我想摆脱所有这些标志/图像,只保留不同语言的字母(和标点符号).
我尝试使用EmojiParser库清理标志:
String withoutEmojis = EmojiParser.removeAllEmojis(input);
问题是EmojiParser无法删除大部分迹象.♦标志是我发现的唯一一个被删除的标志.其他标志如✪✪★✰❈❧✂❋ⓡ♛♛不会被删除.
有没有办法从输入字符串中删除所有这些符号,只保留不同语言中的字母和标点符号?
而不是将某些元素列入黑名单,如何创建您希望保留的角色的白名单?这样您就不必担心每个新的表情符号都会被添加.
String characterFilter = "[^\\p{L}\\p{M}\\p{N}\\p{P}\\p{Z}\\p{Cf}\\p{Cs}\\s]"; String emotiOnless= aString.replaceAll(characterFilter,"");
所以:
[\\p{L}\\p{M}\\p{N}\\p{P}\\p{Z}\\p{Cf}\\p{Cs}\\s]
是一个范围,表示所有numeric(\\p{N}
),letter(\\p{L}
),mark(\\p{M}
),标点符号(\\p{P}
),空格/分隔符(\\p{Z}
),其他格式(\\p{Cf}
)以及U+FFFF
Unicode(\\p{Cs}
)和newline(\\s
)字符中的其他字符.\\p{L}
具体包括其他字母表中的字符,如西里尔字母,拉丁字母,汉字等.
将^
在正则表达式字符集否定匹配.
例:
String str = "hello world _# ??????????????????????"; System.out.print(str.replaceAll("[^\\p{L}\\p{M}\\p{N}\\p{P}\\p{Z}\\p{Cf}\\p{Cs}\\s]","")); // Output: // "hello world _# ??????????????????????"
如果您需要更多信息,请查看正则表达式的Java 文档.
我不是超级Java,所以我不会尝试内联编写示例代码,但我这样做的方法是检查Unicode称为每个字符的"常规类别".有几个字母和标点符号类别.
您可以使用Character.getType查找给定字符的常规类别.您应该保留属于这些常规类别的字符:
COMBINING_SPACING_MARK CONNECTOR_PUNCTUATION CURRENCY_SYMBOL DASH_PUNCTUATION DECIMAL_DIGIT_NUMBER ENCLOSING_MARK END_PUNCTUATION FINAL_QUOTE_PUNCTUATION FORMAT INITIAL_QUOTE_PUNCTUATION LETTER_NUMBER LINE_SEPARATOR LOWERCASE_LETTER MATH_SYMBOL MODIFIER_LETTER MODIFIER_SYMBOL NON_SPACING_MARK OTHER_LETTER OTHER_NUMBER OTHER_PUNCTUATION PARAGRAPH_SEPARATOR SPACE_SEPARATOR START_PUNCTUATION TITLECASE_LETTER UPPERCASE_LETTER
(您列出的所有特别想要删除的字符都有一般类别OTHER_SYMBOL
,我没有在上面的类别列入白名单.)
基于完整的表情符号列表,v11.0,您有1644个不同的Unicode代码点要删除.例如?
,在此列表中U+2705
.
拥有表情符号的完整列表,您需要使用代码点过滤它们.迭代单个char
或byte
不作为单个代码点可以跨越多个字节.因为Java使用UTF-16 emojis通常需要两个char
s.
String input = "ab?cd"; for (int i = 0; i从Unicode代码点
U+2705
到Java的映射int
非常简单:int viSign = 0x2705;或者因为Java支持Unicode字符串:
int viSign = "?".codePointAt(0);
这基本上与EmojiParser使用的方法相同,并且很快就会出于同样的原因而失败.新的表情符号相对频繁地添加到Unicode字符数据库中,如果您现在使用当前定义的1644表情符号实现负规则集的解决方案,则只要新的表情符号可用,实现就会失败.
非常有用的清单.有趣的是,名为removeAllEmojis的方法称为EmojiParser的东西无法处理这些...... :-)
@Bergi:不,因为`input.codePointAt`最多只能查看2个字符,这是一个不变的上限.另外(新添加的)`i + = Character.charCount(cp)`跳过`input.codePointAt`检查过的所有字符(在某些极端情况下减去1).
@OlivierGrégoire:`String.chars()`流过字符而不是代码点.有一个单独的方法[`String.codePoints()`](https://docs.oracle.com/javase/10/docs/api/java/lang/String.html#codePoints()).
这里至少有两个问题:你使用的是一个"封闭的"表情符号列表,所以每年你都要扩展它(但这可能不容易解决),这段代码可能无法正常使用代码点序列(参见https://unicode.org/Public/emoji/11.0/emoji-zwj-sequences.txt)
这将使孤立的零宽度连接器乱丢你的琴弦.
`codePointAt`可能是线性时间,所以整个循环会有二次复杂度?
@TJCrowder因为[他们不是表情符号(根据Unicode标准)](/sf/ask/17360801/#comment86032854_49510006)
这个答案似乎与目前的工作解决方案相差甚远.将所有表情符号收集到适当的格式并非易事.
4> Daniel F..:ICU4J是你的朋友.
UCharacter.hasBinaryProperty(UProperty.EMOJI);请记住保持您的icu4j版本是最新的,请注意这只会过滤掉官方的Unicode表情符号,而不是符号字符.结合并根据需要过滤掉其他字符类型.
更多信息:http: //icu-project.org/apiref/icu4j/com/ibm/icu/lang/UProperty.html#EMOJI
5> Marcos Zolno..:我在下面给出了一些例子,并认为拉丁语已经足够了,但......
有没有办法从输入字符串中删除所有这些符号,只保留不同语言中的字母和标点符号?
在编辑之后,使用该
Character.getType
方法开发了一种新的解决方案,这似乎是最好的解决方案.package zmarcos.emoji; import java.util.Arrays; import java.util.HashSet; import java.util.Set; public class TestEmoji { public static void main(String[] args) { String[] arr = {"Remove ?, , ? , ? and other such signs from Java string", "? Cats and dogs", "I'm on ", "Apples ? ", "? Vi sign", "? I'm the king ? ", "Star me ?", "Star ? once more", "??? ?", "???????? ?"}; System.out.println("---only letters and spaces alike---\n"); for (String input : arr) { int[] filtered = input.codePoints().filter((cp) -> Character.isLetter(cp) || Character.isWhitespace(cp)).toArray(); String result = new String(filtered, 0, filtered.length); System.out.println(input); System.out.println(result); } System.out.println("\n---unicode blocks white---\n"); SetwhiteList = new HashSet<>(); whiteList.add(Character.UnicodeBlock.BASIC_LATIN); for (String input : arr) { int[] filtered = input.codePoints().filter((cp) -> whiteList.contains(Character.UnicodeBlock.of(cp))).toArray(); String result = new String(filtered, 0, filtered.length); System.out.println(input); System.out.println(result); } System.out.println("\n---unicode blocks black---\n"); Set blackList = new HashSet<>(); blackList.add(Character.UnicodeBlock.EMOTICONS); blackList.add(Character.UnicodeBlock.MISCELLANEOUS_TECHNICAL); blackList.add(Character.UnicodeBlock.MISCELLANEOUS_SYMBOLS); blackList.add(Character.UnicodeBlock.MISCELLANEOUS_SYMBOLS_AND_ARROWS); blackList.add(Character.UnicodeBlock.MISCELLANEOUS_SYMBOLS_AND_PICTOGRAPHS); blackList.add(Character.UnicodeBlock.ALCHEMICAL_SYMBOLS); blackList.add(Character.UnicodeBlock.TRANSPORT_AND_MAP_SYMBOLS); blackList.add(Character.UnicodeBlock.GEOMETRIC_SHAPES); blackList.add(Character.UnicodeBlock.DINGBATS); for (String input : arr) { int[] filtered = input.codePoints().filter((cp) -> !blackList.contains(Character.UnicodeBlock.of(cp))).toArray(); String result = new String(filtered, 0, filtered.length); System.out.println(input); System.out.println(result); } System.out.println("\n---category---\n"); int[] category = {Character.COMBINING_SPACING_MARK, Character.COMBINING_SPACING_MARK, Character.CONNECTOR_PUNCTUATION, /*Character.CONTROL,*/ Character.CURRENCY_SYMBOL, Character.DASH_PUNCTUATION, Character.DECIMAL_DIGIT_NUMBER, Character.ENCLOSING_MARK, Character.END_PUNCTUATION, Character.FINAL_QUOTE_PUNCTUATION, /*Character.FORMAT,*/ Character.INITIAL_QUOTE_PUNCTUATION, Character.LETTER_NUMBER, Character.LINE_SEPARATOR, Character.LOWERCASE_LETTER, /*Character.MATH_SYMBOL,*/ Character.MODIFIER_LETTER, /*Character.MODIFIER_SYMBOL,*/ Character.NON_SPACING_MARK, Character.OTHER_LETTER, Character.OTHER_NUMBER, Character.OTHER_PUNCTUATION, /*Character.OTHER_SYMBOL,*/ Character.PARAGRAPH_SEPARATOR, /*Character.PRIVATE_USE,*/ Character.SPACE_SEPARATOR, Character.START_PUNCTUATION, /*Character.SURROGATE,*/ Character.TITLECASE_LETTER, /*Character.UNASSIGNED,*/ Character.UPPERCASE_LETTER}; Arrays.sort(category); for (String input : arr) { int[] filtered = input.codePoints().filter((cp) -> Arrays.binarySearch(category, Character.getType(cp)) >= 0).toArray(); String result = new String(filtered, 0, filtered.length); System.out.println(input); System.out.println(result); } } } 输出:
---only letters and spaces alike--- Remove ?, , ? , ? and other such signs from Java string Remove and other such signs from Java string ? Cats and dogs Cats and dogs I'm on Im on Apples ? Apples ? Vi sign Vi sign ? I'm the king ? Im the king Star me ? Star me Star ? once more Star once more ??? ? ??? ???????? ? ???????? ---unicode blocks white--- Remove ?, , ? , ? and other such signs from Java string Remove , , , and other such signs from Java string ? Cats and dogs Cats and dogs I'm on I'm on Apples ? Apples ? Vi sign Vi sign ? I'm the king ? I'm the king Star me ? Star me Star ? once more Star once more ??? ? ???????? ? ---unicode blocks black--- Remove ?, , ? , ? and other such signs from Java string Remove , , , and other such signs from Java string ? Cats and dogs ? Cats and dogs I'm on I'm on Apples ? Apples ? Vi sign Vi sign ? I'm the king ? I'm the king Star me ? Star me Star ? once more Star once more ??? ? ??? ???????? ? ???????? ---category--- Remove ?, , ? , ? and other such signs from Java string Remove , , , and other such signs from Java string ? Cats and dogs Cats and dogs I'm on I'm on Apples ? Apples ? Vi sign Vi sign ? I'm the king ? I'm the king Star me ? Star me Star ? once more Star once more ??? ? ??? ???????? ? ????????该代码通过将String流式传输到代码点来工作.然后使用lambdas将字符过滤到
int
数组中,然后我们将数组转换为String.该字母和空格使用使用字符方法来过滤,没有标点符号好.尝试失败.
所述的unicode块白色滤波器使用Unicode块程序员指定为允许.尝试失败.
所述的unicode块黑色滤波器使用Unicode块程序员指定为不允许的.尝试失败.
使用静态方法的类别过滤器
Character.getType
.程序员可以在category
数组中定义允许哪些类型.工作.
请注意,Java语言支持较新的Unicode版本有点慢...例如,Java 10仅支持Unicode 8(因此其字符类仅描述Unicode 8字符)...所以很多表情符号都不是presente(请参阅https:/ /docs.oracle.com/javase/10/docs/api/java/lang/Character.html,*字符信息基于Unicode标准版本8.0.0.*)