我有一些字符串,其中包含各种不同的表情符号/图像/标志。
并非所有字符串都是英文的——其中一些是其他非拉丁语言的,例如:
▓ 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 library 清理标志:
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] 是一个范围代表所有数字(\\p{N})、字母(\\p{L})、标记(\\p{M})、标点符号(\\p{P})、空格/分隔符(\\p{ Z})、其他格式 (\\p{Cf}) 和 Unicode 中 U+FFFF 以上的其他字符 (\\p{Cs}) 和换行符 (\\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 documentation 中的正则表达式。
我对 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
,我没有将其包括在上述类别白名单中。)
Character.getType()
不会告诉您您的 char
(或 int
代码点,因为该方法已重载)是否是表情符号、音乐符号或表情符号等。如果您有一个简单的用例,沿着这条路走下去可能很好——这当然是一种易于理解的优雅方法——但请注意,如果需求发生变化,它可能会中断。
根据 Full Emoji List, v11.0,您有 1644 个不同的 Unicode 代码点要删除。例如 ✅
在此列表中为 U+2705
。
拥有完整的表情符号列表,您需要使用 code points 将它们过滤掉。迭代单个 char
或 byte
将不起作用,因为单个代码点可以跨越多个字节。因为 Java 使用 UTF-16 表情符号通常需要两个 char
。
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);
input.codePointAt
最多只能查看 2 个字符,这是一个恒定的上限。此外(新添加的)i += Character.charCount(cp)
会跳过 input.codePointAt
检查的所有字符(在某些极端情况下减去 1)。
String.chars()
流过字符而不是代码点。为此有一个单独的方法 String.codePoints()
。
ICU4J 是你的朋友。
UCharacter.hasBinaryProperty(UProperty.EMOJI);
请记住使您的 icu4j 版本保持最新,并注意这只会过滤掉官方的 Unicode 表情符号,而不是符号字符。根据需要结合过滤掉其他字符类型。
更多信息:http://icu-project.org/apiref/icu4j/com/ibm/icu/lang/UProperty.html#EMOJI
我在下面举了一些例子,并认为拉丁语就足够了,但是......
有没有办法从输入字符串中删除所有这些符号并只保留不同语言的字母和标点符号?
编辑后,使用 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 块。尝试失败。
category 过滤器使用静态方法 Character.getType
。程序员可以在 category
数组中定义允许的类型。 工作😨😱😰😲😀。
import java.lang.Character.UnicodeBlock;
,然后是 Character.UnicodeBlock
-> UnicodeBlock
。
white list
示例。
使用一个名为 RM-Emoji 的 jQuery 插件。以下是它的工作原理:
$('#text').remove('emoji').fast()
这是可能会错过一些表情符号的快速模式,因为它使用启发式算法在文本中查找表情符号。使用 .full()
方法扫描整个字符串并保证删除所有表情符号。
不定期副业成功案例分享
[^\w\^\-\[\]\.!@#$%&*\(\)/+'":;~?,]
之类的东西,但这只是我很健壮并尝试收集所有典型的不是符号的字符)。赞成,因为这绝对是一个潜在的解决方案。如果他想添加一些其他语言字符,他可以根据需要将它们添加到表达式中。p{L}
处理非英文字母字符。我希望大家理解,我不能在我的回答中广泛列出所有非英文字母,因为那将是不切实际的冗长。"[^\\p{L}\\p{M}\\p{N}\\p{P}\\p{Z}\\p{Cf}\\s]"
。这允许通用类别字母、标记、数字、标点符号、分隔符和“其他、格式”,以及空格字符,例如制表符和换行符。