regex 从Java字符串中删除表情符号、图片、符号和其他类似的表情符号/图像/符号

5f0d552i  于 12个月前  发布在  Java
关注(0)|答案(8)|浏览(165)

我有一些字符串,里面有各种不同的表情符号/图像/符号。
并不是所有的字符串都是英文的,其中一些是其他非拉丁语的,例如:

▓ 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);


问题是,PakjiParser无法删除大部分的符号。到目前为止,我发现它删除了唯一的符号,其他符号,如★没有删除。🔥
有没有办法从输入字符串中删除所有这些符号,只保留不同语言中的字母和标点符号?

lc8prwob

lc8prwob1#

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

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文档。

d4so4syb

d4so4syb2#

我对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

字符串
(All您列出的特别想要删除的字符具有一般类别OTHER_SYMBOL,我没有包括在上面的类别白名单中。

brgchamk

brgchamk3#

基于Full Emoji List, v11.0,您有1644个不同的Unicode码位要删除。例如,在此列表中为U+2705
有了完整的表情符号列表,你需要使用code points过滤掉它们。迭代单个charbyte将不起作用,因为单个代码点可以跨越多个字节。因为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的Map很简单:

int viSign = 0x2705;


Java支持Unicode字符串:

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

rggaifut

rggaifut4#

ICU4J是你的朋友。

UCharacter.hasBinaryProperty(UProperty.EMOJI);

字符串
请记住保持您的icu4j版本为最新版本,并注意这只会过滤出官方Unicode表情符号,而不是符号字符。根据需要,合并与过滤出其他字符类型相结合。
更多信息:http://icu-project.org/apiref/icu4j/com/ibm/icu/lang/UProperty.html#EMOJI

b91juud3

b91juud35#

我在下面举了一些例子,并认为拉丁语就足够了,但是......
有没有办法从输入字符串中删除所有这些符号,只保留不同语言中的字母和标点符号?
编辑后,开发了一个新的解决方案,使用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
早上好 ♛
早上好 
Καλημέρα ✂
Καλημέρα


该代码的工作原理是将String流到代码点。然后使用Rolldas将字符过滤到int数组中,然后将数组转换为String。

字母和空格正在使用Character方法进行过滤,不适合标点符号。尝试失败
Unicode块白色过滤器使用程序员指定为允许的Unicode块。尝试失败
unicode blocks black过滤器使用程序员指定为不允许的unicode块。尝试失败
category过滤器使用静态方法Character.getType。程序员可以在category数组中定义允许的类型。WORKS工程师团队😨😱😰😲😀

am46iovg

am46iovg6#

试试这个项目simple-emoji-4j
兼容ji 12.0(2018.10.15)
简单的:

EmojiUtils.removeEmoji(str)

字符串

bxpogfeg

bxpogfeg7#

Java 21有一个新的IsEmoji字符类:

var regex = "\\p{IsEmoji}";

字符串

删除所有表情符号:

var myString = "This is a ⭐ emoji and a \uD83C\uDF0D emoji";
var emojiRegex = "\\p{IsEmoji}";
var myStringWithoutEmojis = myString.replaceAll(emojiRegex, "");

提取所有表情:

var myString = "This is a ⭐ emoji and a \uD83C\uDF0D emoji";
var emojiRegex = "\\p{IsEmoji}";
var pattern = Pattern.compile(emojiRegex);
var matcher = pattern.matcher(myString);
var emojis = matcher.results().map(MatchResult::group).toList();
var emojisString = String.join(" ", emojis);

pbgvytdp

pbgvytdp8#

使用一个名为RM-Jumeji的jQuery插件。它的工作原理如下:

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

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

相关问题