son simbolo signo operadores operador manejo los funcion ejemplos cuales concepto asignacion java regex syntax replace backreference

java - simbolo - operador de asignacion ejemplos



Backreferences Sintaxis en cadenas de reemplazo(¿Por qué signo de dólar?) (2)

En Java, y parece que en algunos otros idiomas, las referencias en el patrón van precedidas de una barra invertida (por ejemplo, /1 , /2 , /3 , etc.), pero en una cadena de reemplazo van precedidas por un signo de dólar (por ejemplo, $1 , $2 , $3 y también $0 ).

Aquí hay un fragmento para ilustrar:

System.out.println( "left-right".replaceAll("(.*)-(.*)", "//2-//1") // WRONG!!! ); // prints "2-1" System.out.println( "left-right".replaceAll("(.*)-(.*)", "$2-$1") // CORRECT! ); // prints "right-left" System.out.println( "You want million dollar?!?".replaceAll("(//w*) dollar", "US//$ $1") ); // prints "You want US$ million?!?" System.out.println( "You want million dollar?!?".replaceAll("(//w*) dollar", "US$ //1") ); // throws IllegalArgumentException: Illegal group reference

Preguntas:

  • ¿El uso de $ para backreferences en cadenas de reemplazo exclusivo de Java? Si no, ¿qué idioma comenzó? ¿Qué sabores lo usan y qué no?
  • ¿Por qué es esta una buena idea? ¿Por qué no apegarse a la misma sintaxis de patrón? ¿No conduciría eso a un lenguaje más cohesivo y más fácil de aprender?
    • ¿No sería más sintaxis la sintaxis si las declaraciones 1 y 4 en el anterior fueran las "correctas" en lugar de 2 y 3?

¿El uso de $ para backreferences en cadenas de reemplazo exclusivo de Java?

No. Perl lo usa, y Perl ciertamente es anterior a la clase de Pattern de Java. El soporte de expresiones regulares de Java se describe explícitamente en términos de expresiones regulares de Perl.

Por ejemplo: http://perldoc.perl.org/perlrequick.html#Search-and-replace

¿Por qué es esta una buena idea?

¡Bueno, obviamente no crees que sea una buena idea! Pero una de las razones por las que es una buena idea es hacer que el soporte de búsqueda / reemplazo de Java (más) sea compatible con Perl.

Hay otra posible razón por la cual $ podría haber sido visto como una mejor opción que / . Es decir que / tiene que escribirse como // en un literal de Java String.

Pero todo esto es pura especulación. Ninguno de nosotros estaba en la sala cuando se tomaron las decisiones de diseño. Y en última instancia, realmente no importa por qué diseñaron la sintaxis de cadenas de reemplazo de esa manera. Las decisiones se tomaron y se establecieron en forma concreta, y cualquier discusión posterior es puramente académica ... a menos que usted esté diseñando un nuevo idioma o una nueva biblioteca de expresiones regulares para Java.


Después de investigar un poco, entendí los problemas ahora: Perl tuvo que usar un símbolo diferente para las referencias de patrones y las referencias de reemplazo, y aunque java.util.regex.* No tiene que seguir el ejemplo, elige, no para una razón técnica, pero bastante tradicional.

En el lado de Perl

(Tenga en cuenta que todo lo que sé sobre Perl en este momento proviene de leer artículos de Wikipedia, así que puede corregir cualquier error que pueda haber cometido)

La razón por la que tuvo que hacerse de esta manera en Perl es la siguiente:

  • Perl usa $ como sigilo (es decir, un símbolo adjunto al nombre de la variable).
  • Los literales de cadena Perl son interpolados de forma variable.
  • Perl regex realmente captura grupos como variables $1 , $2 , etc.

Por lo tanto, debido a la forma en que se interpreta Perl y cómo funciona su motor de expresiones regulares, debe usarse una barra diagonal previa para referencias posteriores (por ejemplo, /1 ) en el patrón, porque si se usa el símbolo $ (por ejemplo, $1 ) causaría involuntariamente interpolación variable en el patrón.

La cadena de reemplazo, debido a cómo funciona en Perl, se evalúa dentro del contexto de cada coincidencia. Es más natural que Perl use interpolación variable aquí, por lo que el motor de expresiones regulares captura grupos en variables $1 , $2 , etc., para que esto funcione sin problemas con el resto del lenguaje.

Referencias

En el lado de Java

Java es un lenguaje muy diferente de Perl, pero lo más importante es que no hay interpolación variable. Además, replaceAll es una llamada a método, y como con todas las llamadas a métodos en Java, los argumentos se evalúan una vez, antes de invocar el método.

Por lo tanto, la característica de interpolación variable por sí sola no es suficiente, ya que en esencia, la cadena de reemplazo se debe volver a evaluar en cada coincidencia, y esa no es la semántica de las llamadas a métodos en Java. Una cadena de reemplazo interpolada variable que se evalúa antes de replaceAll el replaceAll es prácticamente inútil; la interpolación debe suceder durante el método, en cada coincidencia.

Como esa no es la semántica del lenguaje Java, replaceAll debe hacer esta interpolación "just-in-time" manualmente . Como tal, no hay absolutamente ninguna razón técnica por la cual $ sea ​​el símbolo de escape para las referencias en las cadenas de reemplazo. Podría haber sido muy bien el / . Por el contrario, las referencias en el patrón también podrían haberse escapado con $ lugar de / , y todavía habría funcionado tan bien técnicamente.

La razón por la que Java descomprime la forma en que lo hace es puramente tradicional: simplemente sigue el precedente establecido por Perl.