Saltar al contenido

¿Cuál es la expresión regular para extraer todos los emojis de un string?

Después de consultar especialistas en esta materia, programadores de deferentes áreas y maestros dimos con la solución al dilema y la compartimos en este post.

Solución:

Usando emoji-java, escribí un método simple que elimina todos los emojis, incluidos los modificadores fitzpatrick. Requiere una biblioteca externa pero más fácil de mantener que esas expresiones regulares de monstruos.

Usar:

String input = "A string with a uD83DuDC66uD83CuDFFFfew emojis!";
String result = EmojiParser.removeAllEmojis(input);

Instalación de emoji-java maven:


  com.vdurmont
  emoji-java
  3.1.3

gradle:

implementation 'com.vdurmont:emoji-java:3.1.3'

EDITAR: la respuesta enviada anteriormente se incorporó al código fuente emoji-java.

el pdf que acaba de mencionar dice Rango: 1F300–1F5FF para símbolos y pictogramas varios. Entonces, digamos que quiero capturar cualquier personaje que se encuentre dentro de este rango. ¿Ahora qué hacer?

De acuerdo, ¡pero solo señalaré que los emoji en tu pregunta están fuera de ese rango! 🙂

El hecho de que estos estén por encima 0xFFFF complica las cosas, porque las cadenas de Java almacenan UTF-16. Por lo tanto, no podemos usar simplemente una clase de carácter simple para ello. Vamos a tener pares sustitutos. (Más: http://www.unicode.org/faq/utf_bom.html)

U + 1F300 en UTF-16 termina siendo la pareja uD83CuDF00; U + 1F5FF termina siendo uD83DuDDFF. Tenga en cuenta que el primer carácter subió, cruzamos al menos un límite. Así que tenemos que saber qué rangos de pares sustitutos estamos buscando.

Al no estar inmerso en el conocimiento sobre el funcionamiento interno de UTF-16, escribí un programa para averiguarlo (fuente al final: lo verificaría dos veces si fuera usted, en lugar de confiar en mí). Me dice que estamos buscando uD83C seguido de cualquier cosa en el rango uDF00-uDFFF (inclusive), o uD83D seguido de cualquier cosa en el rango uDC00-uDDFF (inclusivo).

Así que armados con ese conocimiento, en teoría ahora podríamos escribir un patrón:

// This is wrong, keep reading
Pattern p = Pattern.compile("(?:uD83C[uDF00-uDFFF])|(?:uD83D[uDC00-uDDFF])");

Esa es una alternancia de dos grupos que no capturan, el primer grupo para las parejas que comienzan con uD83C, y el segundo grupo para las parejas que comienzan con uD83D.

Pero eso falla (no encuentra nada). Estoy bastante seguro de que es porque estamos tratando de especificar mitad de una pareja sustituta en varios lugares:

Pattern p = Pattern.compile("(?:uD83C[uDF00-uDFFF])|(?:uD83D[uDC00-uDDFF])");
// Half of a pair --------------^------^------^-----------^------^------^

No podemos simplemente dividir pares sustitutos así, se llaman sustitutos pares por una razón. 🙂

En consecuencia, no creo que podamos usar expresiones regulares (o de hecho, cualquier stringenfoque basado en) para esto en absoluto. Creo que tenemos que buscar a través char matrices.

char las matrices contienen valores UTF-16, por lo que pueden encontrar esos medios pares en los datos si los buscamos de la manera difícil:

String s = new StringBuilder()
                .append("Thats a nice joke ")
                .appendCodePoint(0x1F606)
                .appendCodePoint(0x1F606)
                .appendCodePoint(0x1F606)
                .append(" ")
                .appendCodePoint(0x1F61B)
                .toString();
char[] chars = s.toCharArray();
int index;
char ch1;
char ch2;

index = 0;
while (index < chars.length - 1)  // -1 because we're looking for two-char-long things
    ch1 = chars[index];
    if ((int)ch1 == 0xD83C) 
        ch2 = chars[index+1];
        if ((int)ch2 >= 0xDF00 && (int)ch2 <= 0xDFFF) 
            System.out.println("Found emoji at index " + index);
            index += 2;
            continue;
        
    
    else if ((int)ch1 == 0xD83D) 
        ch2 = chars[index+1];
        if ((int)ch2 >= 0xDC00 && (int)ch2 <= 0xDDFF) 
            System.out.println("Found emoji at index " + index);
            index += 2;
            continue;
        
    
    ++index;

Obviamente, eso es solo código de nivel de depuración, pero funciona. (En tu dado string, con su emoji, por supuesto que no encontrará nada ya que están fuera del rango. Pero si cambia el límite superior del segundo par a 0xDEFF en lugar de 0xDDFF, va a. Sin embargo, no tengo idea de si eso también incluiría los no emojis).


Fuente de mi programa para averiguar cuáles eran los rangos sustitutos:

public class FindRanges 

    public static void main(String[] args) 
        char last0 = '';
        char last1 = '';
        for (int x = 0x1F300; x <= 0x1F5FF; ++x) 
            char[] chars = new StringBuilder().appendCodePoint(x).toString().toCharArray();
            if (chars[0] != last0) 
                if (last0 != '') 
                    System.out.println("-\u" + Integer.toHexString((int)last1).toUpperCase());
                
                System.out.print("\u" + Integer.toHexString((int)chars[0]).toUpperCase() + " \u" + Integer.toHexString((int)chars[1]).toUpperCase());
                last0 = chars[0];
            
            last1 = chars[1];
        
        if (last0 != '') 
            System.out.println("-\u" + Integer.toHexString((int)last1).toUpperCase());
        
    

Producción:

uD83C uDF00-uDFFF
uD83D uDC00-uDDFF

Tuvo un problema similar. Lo siguiente me sirvió bien y coincide con pares sustitutos

public class SplitByUnicode 
    public static void main(String[] argv) throws Exception 
        String string = "Thats a nice joke  ";
        System.out.println("Original String:"+string);
        String regexPattern = "[uD83C-uDBFFuDC00-uDFFF]+";
        byte[] utf8 = string.getBytes("UTF-8");

        String string1 = new String(utf8, "UTF-8");

        Pattern pattern = Pattern.compile(regexPattern);
        Matcher matcher = pattern.matcher(string1);
        List matchList = new ArrayList();

        while (matcher.find()) 
            matchList.add(matcher.group());
        

        for(int i=0;i

La salida es:


Original String:Thats a nice joke  
0:
1:

Encontré la expresión regular de https://stackoverflow.com/a/24071599/915972

Nos encantaría que puedieras recomendar este ensayo si te fue de ayuda.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *