从Java字符串中删除✅,🔥,,♛等表情符号/图像/符号

我有一些字符串,里面有各种不同的表情符号/图像/符号。

并不是所有的字符串都是英语——其中一些是其他非拉丁语言,例如:

▓ 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不能删除大部分符号。♦符号是迄今为止我发现的唯一一个被移除的符号。 其他标志,如:✿❉★❈❧✿❋●✿♛🔥不移除

有没有办法从输入字符串中删除所有这些符号,只保留不同的语言中的字母和标点符号?

43856 次浏览

基于完整的表情符号列表,v11.0,你有1644个不同的Unicode代码点要删除。例如,在这个列表中是U+2705

有了完整的表情符号列表,你需要使用代码点将它们过滤掉。遍历单个charbyte将不起作用,因为单个代码点可以跨越多个字节。因为Java使用UTF-16表情符号通常会有两个__abc。

String input = "ab✅cd";
for (int i = 0; i < input.length();) {
int cp = input.codePointAt(i);
// filter out if matches
i += Character.charCount(cp);
}

从Unicode代码点U+2705映射到Java int很简单:

int viSign = 0x2705;

或者因为Java支持Unicode字符串:

int viSign = "✅".codePointAt(0);

与其将某些元素列入黑名单,不如创建一个您希望保留的字符白名单?这样你就不需要担心每一个新的表情符号被添加。

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]是一个范围,表示Unicode (\\p{Cs})中所有数字(\\p{N})、字母(\\p{L})、标记(\\p{M})、标点符号(\\p{P})、空格/分隔符(\\p{Z})、其他格式(\\p{Cf})和其他高于U+FFFF的字符(\\s)。\\p{N}1包含来自其他字母的字符,如西里尔字母,拉丁语,汉字等。
  • 正则表达式字符集中的^将取消匹配。

例子:

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,我没有包括在上面的类别白名单中。)

我在下面举了几个例子,觉得拉丁文就够了,但是……

是否有方法从输入字符串中删除所有这些符号 只保留信件&不同语言中的标点符号?< / p >

编辑后,使用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");
Set<Character.UnicodeBlock> whiteList = 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<Character.UnicodeBlock> 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
早上好 ♛
早上好
Καλημέρα ✂
Καλημέρα

该代码通过将字符串流式传输到代码点来工作。然后使用lambdas将字符过滤为int数组,然后将数组转换为String。

字母和空格正在使用Character方法来过滤,不适合使用标点符号。失败的尝试

使用程序员指定的允许的unicode块的Unicode阻止白色过滤器。失败的尝试

使用程序员指定为不允许的unicode块的Unicode屏蔽黑色过滤器。失败的尝试

使用静态方法Character.getType类别过滤器。程序员可以在category数组中定义允许的类型。作品😨😱😰😲😀。

ICU4J是您的朋友。

UCharacter.hasBinaryProperty(UProperty.EMOJI);

请记住保持您的icu4j版本是最新的,并注意这只会过滤掉官方的Unicode表情符号,而不是符号字符。结合过滤所需的其他字符类型。

< p >更多信息: http://icu-project.org/apiref/icu4j/com/ibm/icu/lang/UProperty.html#EMOJI < / p >

使用jQuery插件RM-Emoji。下面是它的工作原理:

$('#text').remove('emoji').fast()

这是快速模式,可能会错过一些表情符号,因为它使用启发式算法在文本中查找表情符号。使用.full()方法扫描整个字符串,并确保删除所有表情符号。

试试这个项目simple-emoji-4j

兼容Emoji 12.0 (2018.10.15)

简单的有:

EmojiUtils.removeEmoji(str)