Agrupación y reemplazo de expresiones regulares de Java

La subexpresión (agrupación) de expresiones regulares no es muy fácil de entender, pero es una herramienta de procesamiento de texto muy poderosa.

1 Calentamiento de expresión regular

Coincidir con el número de teléfono
// 电话号码匹配
// 手机号段只有 13xxx 15xxx 18xxxx 17xxx
System.out.println("18304072984".matches("1[3578]\\d{9}"));   // true

// 座机号:010-65784236,0316-3312617,022-12465647,03123312336
String regex = "0\\d{2}-?\\d{8}|0\\d{3}-?\\d{7}";
String telStr = "010-43367458";
System.out.println(telStr.matches(regex));  // true
Coincidir con el buzón
String mail = "[email protected]";
String reg = "[a-zA-Z_0-9]+@[a-zA-Z0-9]+(\\.[a-zA-Z]+){1,2}";
System.out.println(mail.matches(reg));  // true
Reemplazo de caracteres especiales

Reemplace los caracteres que no sean chinos por vacíos:

String input = "神探狄仁&*%$杰之四大天王@bdfbdbdfdgds23532";
String reg = "[^\\u4e00-\\u9fa5]";
input = input.replaceAll(reg, "");
System.out.println(input);   // 神探狄仁杰之四大天王

El rango de codificación Unicode de caracteres chinos es:\u4e00-\u9fa5

2 Grupo

Un grupo es una expresión regular dividida entre paréntesis, y se puede hacer referencia a un grupo según su número. El número de grupo 0 representa la expresión completa, el número de grupo 1 representa el grupo encerrado por el primer par de paréntesis, y así sucesivamente.
Consulte la descripción en Patrón en la API de Java: Los
grupos de captura se numeran contando sus paréntesis de apertura de izquierda a derecha. En la expresión ((A)(B(C))), por ejemplo, hay cuatro grupos de este tipo:

1. ((A)(B(C)))
2. (A)
3. (B(C))
4. (C)

Otro ejemplo A(B(C))Dtiene tres grupos: el grupo 0 es ABCD, el grupo 1 es BC, el grupo 2 es C,
dependiendo de cuántos paréntesis a la izquierda para determinar cuántos paquetes de expresiones de paréntesis se denominan sub-expresión.

Ej. 1:

El objeto Matcher proporciona muchos métodos:

  1. goupCount() Devuelve el número de grupos en el patrón de expresión regular, correspondiente al número de "corchetes izquierdos"
  2. group(int i) Devuelve el carácter coincidente del grupo correspondiente, o nulo si no se encuentra ninguna coincidencia
  3. start(int group) Devuelve el índice inicial del carácter coincidente del grupo correspondiente.
  4. end(int group) Devuelve el valor del índice del último carácter del carácter coincidente en el grupo correspondiente más uno
// 这个正则表达式有两个组,
// group(0) 是 \\$\\{([^{}]+?)\\}
// group(1) 是 ([^{}]+?)
String regex = "\\$\\{([^{}]+?)\\}";
Pattern pattern = Pattern.compile(regex);
String input = "${name}-babalala-${age}-${address}";

Matcher matcher = pattern.matcher(input);
System.out.println(matcher.groupCount());
// find() 像迭代器那样向前遍历输入字符串
while (matcher.find()) {
    
    
    System.out.println(matcher.group(0) + ", pos: "
            + matcher.start() + "-" + (matcher.end() - 1));
    System.out.println(matcher.group(1) + ", pos: " +
            matcher.start(1) + "-" + (matcher.end(1) - 1));
}

Salida:

1
${name}, pos: 0-6
name, pos: 2-5
${age}, pos: 17-22
age, pos: 19-21
${address}, pos: 24-33
address, pos: 26-32

group, Traducido al chino significa agrupación.
group()O group(0)correspondiente al contenido que coincide con la expresión regular completa cada vez,
group(1)indicando el contenido que coincide entre paréntesis (un grupo de subexpresión).

Ej. 2:

Para ver la agrupación de manera más intuitiva, agregue un par de paréntesis a la expresión regular de Eg1:

String regex = "(\\$\\{([^{}]+?)\\})";
Pattern pattern = Pattern.compile(regex);
String input = "${name}-babalala-${age}-${address}";

Matcher matcher = pattern.matcher(input);
// matcher.find() 方法会对 input 这个字符串多次进行匹配,如果能匹配到,这个匹配结果里就会包含多个分组,我们可以从分组里提取我们想要的结果
while (matcher.find()) {
    
    
    System.out.println(matcher.group(0) + ", pos: " + matcher.start());
    System.out.println(matcher.group(1) + ", pos: " + matcher.start(1));
    System.out.println(matcher.group(2) + ", pos: " + matcher.start(2));
}

Salida:

${name}, pos: 0
${name}, pos: 0
name, pos: 2
${age}, pos: 17
${age}, pos: 17
age, pos: 19
${address}, pos: 24
${address}, pos: 24
address, pos: 26

A partir de esto, se pueden obtener un par de paréntesis y se puede usar el número de paréntesis izquierdos para determinar cuántos grupos hay.

Los group()escenarios de aplicación para obtener cadenas coincidentes en la agrupación son muy amplios
En uno de los proyectos del autor, hemos realizado una sustitución de comodines muy interesante utilizando esta función, ¡así que movido!

Eg3 (para extraer los datos deseados por agrupación):
        // 这个正则表达式会提取字符串中的「数字」和「字母」
        Pattern pattern = Pattern.compile("([0-9]+).*?([a-zA-Z]+)");
        String input = "那就20200719这样吧sunny。。。。。。。122432该拿什么与眼泪抗衡twinkle";
        Matcher matcher = pattern.matcher(input);
        // 每个匹配到的子串分组的个数
        int group = matcher.groupCount();
        // 如果输入串有多个可被匹配的子串,这里会多次进行匹配
        while (matcher.find()) {
    
    
            System.out.println("匹配到的子串:" + matcher.group());  // 匹配到的子串
            for (int i = 1; i <= group; i++) {
    
    
                System.out.println("分组" + i + ": " + matcher.group(i));
            }
        }

Salida:

匹配到的子串:20200719这样吧sunny
分组1: 20200719
分组2: sunny
匹配到的子串:122432该拿什么与眼泪抗衡twinkle
分组1: 122432
分组2: twinkle

3 Reemplazo de grupo

Ej. 1:
String tel = "18304072984";
// 括号表示组,被替换的部分$n表示第n组的内容
tel = tel.replaceAll("(\\d{3})\\d{4}(\\d{4})", "$1****$2");
System.out.print(tel);   // output: 183****2984

replaceAll es un método para reemplazar cadenas. Los paréntesis en la expresión regular indican una agrupación. En el parámetro 2 de replaceAll, puede usar $ n (n es un número) para hacer referencia a las cadenas de agrupación que coinciden en la subexpresión a su vez "(\\d{3})\\d{4}(\\d{4})", "$1****$2", divididas en el frente (前三个数字)中间四个数字(最后四个数字)Reemplazar con (第一组数字保持不变 $1)(中间为 * )(第二组数字保持不变 $2).

Ej. 2:
String one = "hello girl hi hot".replaceFirst("(\\w+)\\s+(\\w+)", "$2 $1"); 
String two = "hello girl hi hot".replaceAll("(\\w+)\\s+(\\w+)", "$2 $1"); 
System.out.println(one);   // girl hello hi hot
System.out.println(two);   // girl hello hot hi

Después de entender Eg1, este ejemplo lo entenderá naturalmente.

Eg3:

Aquí hay un ejemplo práctico, reemplazo de puntuación repetido:

String input = "假如生活欺骗了你,,,相信吧,,,快乐的日子将会来临!!!…………";

// 重复标点符号替换
String duplicateSymbolReg = "([。?!?!,]|\\.\\.\\.|……)+";
input = input.replaceAll(duplicateSymbolReg, "$1");
System.out.println(input);

Salida:

假如生活欺骗了你,相信吧,快乐的日子将会来临!……

Expresión regular :, ([。?!?!,]|\\.\\.\\.|……)+entre paréntesis es un grupo: representa un signo de puntuación, lo que +significa que este grupo aparece una o más veces, $1el contenido del grupo (un signo de puntuación). replaceAll se usa $1para reemplazar la cadena.

Eg4:

Clasificación de direcciones IP

String ip = "192.68.1.254 102.49.23.013 10.10.10.10 2.2.2.2 8.109.90.30";
ip = ip.replaceAll("(\\d+)", "00$1");
System.out.println(ip);

ip = ip.replaceAll("0*(\\d{3})", "$1");
System.out.println(ip);
String[] strs = ip.split(" ");

Arrays.sort(strs);
for (String str : strs) {
    str = str.replaceAll("0*(\\d+)", "$1");
    System.out.println(str);
}

Salida:

00192.0068.001.00254 00102.0049.0023.00013 0010.0010.0010.0010 002.002.002.002 008.00109.0090.0030
192.068.001.254 102.049.023.013 010.010.010.010 002.002.002.002 008.109.090.030
2.2.2.2
8.109.90.30
10.10.10.10
102.49.23.13
192.68.1.254
  1. Deje que cada segmento de la dirección IP sea de 3 bits, y hay 4 bits después del reemplazo
  2. Asegúrese de que cada segmento de la dirección IP tenga 3 bits
  3. Algo así como

En este punto, el autor no puede evitar suspirar, ¡realmente poderoso!

4 Volver referencias

Después de usar paréntesis para especificar un grupo de subexpresión, el texto que coincide con esta subexpresión se puede procesar más en la expresión o en otros programas. Por defecto, cada grupo tendrá automáticamente un número de grupo. La regla es: use el paréntesis izquierdo del grupo como marca, de izquierda a derecha, el número de grupo del primer grupo es 1, el segundo es 2, y así sucesivamente.

P.ej:
/* 这个正则表达式表示 安安静静 这样的叠词 */
String regex = "(.)\\1(.)\\2";  
System.out.println("安安静静".matches(regex));   // true
System.out.println("安静安静".matches(regex));   // false

Lo anterior (.)representa un paquete, que .representa cualquier carácter, cada carácter es un paquete,
\\1representa un grupo ( ) apareció nuevamente, \\2representando el grupo 2 ( ) apareció nuevamente.

安静安静¿Cómo escribir expresiones regulares para hacer coincidir ? Según el ejemplo anterior, se 安静dividirá en un grupo, y luego este grupo volverá a aparecer 安静安静:

String regex = "(..)\\1";  
System.out.println("安静安静".matches(regex));   // true
System.out.println("安安静静".matches(regex));   // false

5 Sustitución de referencia inversa

Ej. 1:
String str = "我我...我我...我要..要要...要要...找找找一个....女女女女...朋朋朋朋朋朋...友友友友友..友.友...友...友友!!!";
        
/*将 . 去掉*/
str = str.replaceAll("\\.+", "");
System.out.println(str);

str = str.replaceAll("(.)\\1+", "$1");
System.out.println(str);

Salida:

我我我我我要要要要要找找找一个女女女女朋朋朋朋朋朋友友友友友友友友友友!!!
我要找一个女朋友!

(.)Indica que cualquier personaje se convertirá en un grupo; \\1+citar un grupo (un personaje) significa que este grupo aparece una o más veces. $1La agrupación de citas (.)reemplaza varios caracteres repetidos con un carácter.

Ej. 2:

Reemplaza el contenido entre dos dígitos repetidos:

"xx12abdd12345".replaceAll("(\\d{2}).+?\\1", "");  //结果为 xx345

¿Se siente increíble?

replaceUna excepción a la que se debe prestar atención cuando se utilizan una serie de métodos: el método Java replaceAll () informa un error Referencia de
referencia de grupo ilegal :
Java Regular Chapter-27-Regular Reemplazo y función de agrupación
Expresiones
regulares Tutorial introductorio de 30 minutos Regular Basics-Capture Group (capture group )
Expresión regular de Java Clase Patrón y Matcher
Aprendizaje de Java expresión regular Expresión regular
de uso avanzado de Java para recuperar y reemplazar caracteres específicos en String y todo lo relacionado con la expresión regular
java eliminar espacios y puntuación

Supongo que te gusta

Origin blog.csdn.net/jiaobuchong/article/details/81257570
Recomendado
Clasificación