Ir a contenido principal

Al hacer clic en Enviar, usted está de acuerdo con los términos y condiciones de developerWorks.

La primera vez que inicie sesión en developerWorks, se creará un perfil para usted. Cierta información de su perfil de developerWorks será mostrada públicamente, pero usted puede editar la información en cualquier momento. Su nombre, apellido (a menos que usted elija ocultarlo) y nombre de usuario acompañarán el contenido que usted publique.

Toda la información enviada es segura.

  • Cerrar [x]

La primera vez que inicia sesión en developerWorks se crea un perfil para usted, teniendo que elegir un nombre para mostrar en el mismo. Este nombre acompañará el contenido que usted publique en developerWorks.

Por favor elija un nombre de 3 - 31 caracteres. Su nombre de usuario debe ser único en la comunidad developerWorks y debe ser distinto a su dirección de email por motivos de privacidad.

Al hacer clic en Enviar, usted está de acuerdo con los términos y condiciones de developerWorks.

Toda la información enviada es segura.

  • Cerrar [x]

Introducción a la programación Java, parte 2: Construcciones para aplicaciones del mundo real

Funciones más avanzadas del lenguaje Java

J. Steven Perry, Consultor Director, Makoto Consulting Group, Inc.
J. Steven Perry
J. Steven Perry es desarrollador de software, arquitecto y fanático general de Java que ha estado desarrollando software profesionalmente desde 1991. Sus intereses profesionales abarcan desde el funcionamiento interno de la JVM hasta el modelo UML y todo lo que está en el medio. Steve tiene una pasión por escribir y ser mentor. Es el autor de Java Management Extensions (O'Reilly), Log4j (O'Reilly) y los artículos de developerWorks de IBM "Joda-Time" y OpenID for Java Web applications". Pasa tiempo libre con sus tres hijos, anda en bicicleta y enseña yoga.

Resumen:  En la Parte 1 de este tutorial, el programador Java™ profesional J. Steven Perry presentó la sintaxis del lenguaje Java y las bibliotecas que usted necesita para escribir aplicaciones Java simples. La Parte 2, todavía orientada a desarrolladores nuevos en el desarrollo de aplicaciones Java, presenta las construcciones de programación más sofisticadas requeridas para crear complejas aplicaciones Java del mundo real. Los temas que se cubren incluyen manejo de excepciones, herencia y abstracción, expresiones regulares, genéricos, E/S Java y serialización Java.

Ver más contenido de esta serie

Fecha:  10-12-2012
Nivel:  Introductoria PDF:  A4 and Letter (927 KB | 54 páginas)Get Adobe® Reader®

Comentario:  

Expresiones regulares

Una expresión regular es esencialmente un patrón para describir un conjunto de cadenas que comparten ese patrón. Si usted es un programador Perl, debería sentirse como en su hogar con la sintaxis de patrón de expresión regular (regex) en el lenguaje Java. Sin embargo, si no está acostumbrado a la sintaxis de expresiones regulares, puede parecer raro. En esta sección, usted comienza con el uso de expresiones regulares en sus programas Java.

La API de expresiones regulares

Aquí hay un conjunto de cadenas que tienen algunos aspectos en común:

  • Una cadena
  • Una cadena más larga
  • Una cadena mucho más larga

Observe que cada una de estas cadenas comienza con a y termina con string. La API de expresiones regulares Java (vea Resources) lo ayuda a sacar estos elementos, ver el patrón entre ellos y realizar cosas importantes con la información que ha averiguado.

La API de expresiones regulares tiene tres clases principales que usará casi todo el tiempo:

  • Pattern describe un patrón de cadena.
  • Matcher prueba una cadena para ver si coincide con el patrón.
  • PatternSyntaxException le dice que algo acerca del patrón que usted intentó definir no fue aceptable.

Comenzará trabajando con un patrón simple de expresiones regulares que usa estas clases pronto. Sin embargo, antes de que haga eso, observará la sintaxis del patrón regex.


Sintaxis del patrón regex

Un patrón regex describe la estructura de la cadena que la expresión intentará encontrar en una cadena de entrada. Aquí es donde las expresiones regulares pueden parecer un poco extrañas. De todos modos, una vez que entiende la sintaxis, resulta más fácil de descifrar. La Tabla 2 enumera algunas de las construcciones regex más comunes que usted usará en cadenas de patrones:


Tabla 2. Construcciones regex comunes
Construcción regex¿Qué califica como una coincidencia?
.Cualquier carácter
?Cero (0) o uno (1) de lo que vino anteriormente
*Cero (0) o más de lo que vino anteriormente
+Uno (1) o más de lo que vino anteriormente
[]Un rango de caracteres o dígitos
^Negación de lo que sea que siga (es decir, "notwhatever")
\dCualquier dígito (alternativamente, [0-9])
\DCualquiera que no sea un dígito (alternativamente, [^0-9])
\sCualquier carácter de espacio en blanco (alternativamente, [\n\t\f\r])
\SCualquier carácter sin espacio en blanco (alternativamente, [^\n\t\f\r])
\wCualquier carácter alfanumérico (alternativamente, [a-zA-Z_0-9])
\WCualquier carácter no alfanumérico (alternativamente, [^\w])

Las primeras pocas construcciones se llaman cuantificadoras porque cuantifican lo que está antes que ellas. Las construcciones como \d son clases de caracteres predefinidas. Cualquier carácter que no tenga un significado especial en un patrón es un literal y coincide consigo mismo.

Coincidencia de patrón

Con la sintaxis de patrón de la Tabla 2, puede ocuparse del simple ejemplo del Listado 19, con el uso de clases en la API de expresiones regulares Java:


Listado 19. Coincidencia de patrón con regex

Pattern pattern = Pattern.compile("a.*string");
Matcher matcher = pattern.matcher("a string");
boolean didMatch = matcher.matches();
Logger.getAnonymousLogger().info (didMatch);
int patternStartIndex = matcher.start();
Logger.getAnonymousLogger().info (patternStartIndex);
int patternEndIndex = matcher.end();
Logger.getAnonymousLogger().info (patternEndIndex);

En primer lugar, el Listado 19 crea una clase Pattern al llamar a compile(), que es un método estático en Pattern, con una serie literal que representa el patrón que usted quiere hacer coincidir. Ese literal usa la sintaxis de patrón regex. En este ejemplo, la traducción al español del patrón es la siguiente:

Encuentre una cadena de la forma a seguida por cero caracteres o más, seguidos por la cadena.

Métodos para la coincidencia

Luego, el Listado 19 llama a matcher() en el Pattern. Esa llamada crea una instancia Matcher. Cuando eso sucede, el Matcher busca la cadena que usted pasó para las coincidencias en comparación con la cadena de patrón que usó cuando creó el Pattern.

Cada cadena del lenguaje Java es una colección indexada de caracteres, que comienza desde 0 y termina con la longitud de la cadena menos uno. El Matcher analiza la cadena, que comienza desde 0, y busca coincidencias con ella. Luego de que se completa ese proceso, el Matcher contiene información acerca de las coincidencias encontradas (o no encontradas) en la cadena de entrada. Puede acceder a esa información a llamar a diversos métodos en el Matcher:

  • matches() le dice si toda la secuencia de entrada fue una coincidencia exacta para el patrón.
  • start() le dice el valor de índice en la cadena donde comienza la cadena coincidente.
  • end() le dice el valor de índice en la cadena donde termina la cadena coincidente, más uno.

El Listado 19 encuentra una sola coincidencia al comenzar en 0 y terminar en 7. De este modo, la llamada a matches() retorna true, la llamada a start() retorna 0 y la llamada a end() retorna 8.

lookingAt() versus matches()

Si existieran más elementos en su cadena que los caracteres en el patrón que usted buscó, podría usar lookingAt() en lugar de matches(). lookingAt() busca coincidencias de subcadenas para un patrón dado. Por ejemplo, considere la siguiente cadena:

Aquí hay una cadena que tiene más que solo el patrón.

Podría buscarla para a.*string y obtener una coincidencia si usa lookingAt(). Pero si usa matches(), retornaría false porque la cadena conlleva más que solo lo que está en el patrón.


Patrones complejos en regex

Las búsquedas simples son fáciles con las clases regex, pero también puede hacer algo altamente sofisticado con la API de expresiones regulares.

Un wiki, como seguramente sabe, es un sistema basado en la web que permite a los usuarios modificar páginas. Los wikis se basan casi por completo en expresiones regulares. Su contenido se basa en las entradas de cadenas de los usuarios, lo cual se analiza y formatea con el uso de expresiones regulares. Cualquier usuario puede crear un enlace a otro tema en un wiki al ingresar una palabra wiki, que normalmente es una serie de palabras concatenadas, cada una de las cuales comienza con una letra mayúscula, como la siguiente:

MyWikiWord

Al saber eso acerca de los wikis, asuma la siguiente cadena:

Aquí hay una WikiWord seguida de AnotherWikiWord y luego YetAnotherWikiWord.

Podría buscar palabras wikis en esta cadena con un patrón regex como el siguiente:

[A-Z][a-z]*([A-Z][a-z]*)+

Y aquí hay un código para buscar palabras wikis:

String input = "Here is a WikiWord followed by AnotherWikiWord, then SomeWikiWord.";
Pattern pattern = Pattern.compile("[A-Z][a-z]*([A-Z][a-z]*)+");
Matcher matcher = pattern.matcher(input);
while (matcher.find()) {
 Logger.getAnonymousLogger().info("Found this wiki word: " + matcher.group());
}

Ejecute este código y debería ver las tres palabras wikis en su consola.

Sustitución de cadenas

Buscar coincidencias es útil pero también puede manipular cadenas una vez que encuentra una coincidencia para ellas. Puede hace eso al sustituir cadenas coincidentes con algo más, del mismo modo en que podría buscar algún texto en un programa procesador de textos y sustituirlo con otro texto. Matcher tiene un par de métodos para sustituir elementos de cadenas:

  • replaceAll() sustituye todas las coincidencias con una cadena especificada.
  • replaceFirst() sustituye solo la primera coincidencia con una cadena especificada.

Usar métodos replace de Matcher es sencillo:

String input = "Here is a WikiWord followed by AnotherWikiWord, then SomeWikiWord.";
Pattern pattern = Pattern.compile("[A-Z][a-z]*([A-Z][a-z]*)+");
Matcher matcher = pattern.matcher(input);
Logger.getAnonymousLogger().info("Before: " + input);
String result = matcher.replaceAll("replacement");
Logger.getAnonymousLogger().info("After: " + result);

Este código encuentra palabras wikis, como antes. Cuando el Matcher encuentra una coincidencia, sustituye el texto de la palabra wiki con su sustitución. Cuando usted ejecuta este código, debería ver lo siguiente en su consola:

Antes: Aquí hay una WikiWord seguida de AnotherWikiWord y luego SomeWikiWord.
Después: Aquí hay una sustitución seguida de sustitución y luego sustitución.

Si usted hubiera usado replaceFirst(), habría visto lo siguiente:

Antes: Aquí hay una PalabraWiki seguida de AnotherWikiWord y luego SomeWikiWord.
Después: Aquí hay una sustitución seguida de AnotherWikiWord y luego SomeWikiWord.


Coincidencia y manipulación de grupos

Cuando busca coincidencias con un patrón regex, puede obtener información sobre lo que encontró. Ha visto algo de eso con los métodos start() y end() en el Matcher. Pero también es posible hacer referencia a coincidencias al capturar grupos.

En cada patrón, usted normalmente crea grupos al encerrar partes del patrón en paréntesis. Los grupos se enumeran de izquierda a derecha, comenzando desde 1 (el grupo 0 representa toda la coincidencia). El código en el Listado 20 sustituye cada palabra wiki con una cadena que "envuelve" la palabra:


Listado 20. Coincidencia de grupos

String input = "Here is a WikiWord followed by AnotherWikiWord, then SomeWikiWord.";
Pattern pattern = Pattern.compile("[A-Z][a-z]*([A-Z][a-z]*)+");
Matcher matcher = pattern.matcher(input);
Logger.getAnonymousLogger().info("Before: " + input);
String result = matcher.replaceAll("blah$0blah");
Logger.getAnonymousLogger().info("After: " + result);

Ejecute este código y debería obtener la siguiente salida de la consola:

Antes: Aquí hay una PalabraWiki seguida de AnotherWikiWord y luego SomeWikiWord.
Después: Aquí hay una blahWikiWordblah seguida de blahAnotherWikiWordblah y luego blahSomeWikiWordblah.
|-------10--------20--------30--------40--------50--------60--------70--------80--------9|
|-------- XML error: La línea anterior es más larga que 90 caracteres
    ---------|

Otro abordaje a la coincidencia de grupos

El Listado 20 hace referencia a toda la coincidencia al incluir $0 en la cadena de sustitución. Cualquier parte de una cadena de sustitución de la forma $int se refiere al grupo identificado por el entero (por lo tanto, $1 se refiere al grupo 1 y así sucesivamente). En otras palabras, $0 es equivalente a matcher.group(0);.

Usted podría cumplir el mismo objetivo de sustitución al usar algunos otros métodos. En lugar de llamar a replaceAll(), podría hacer lo siguiente:

StringBuffer buffer = new StringBuffer();
while (matcher.find()) {
 matcher.appendReplacement(buffer, "blah$0blah");
}
matcher.appendTail(buffer);
Logger.getAnonymousLogger().info("After: " + buffer.toString());

Y obtendría el mismo resultado:

Antes: Aquí hay una PalabraWiki seguida de AnotherWikiWord y luego SomeWikiWord.
Después: Aquí hay una blahWikiWordblah seguida de blahAnotherWikiWordblah y luego blahSomeWikiWordblah.
|-------10--------20--------30--------40--------50--------60--------70--------80--------9|
|-------- XML error: La línea anterior es más larga que 90 caracteres
    ---------|

8 de 14 | Anterior | Siguiente

Comentario



static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=90
Zone=tecnologia Java
ArticleID=850709
TutorialTitle=Introducción a la programación Java, parte 2: Construcciones para aplicaciones del mundo real
publish-date=12102012
author1-email=steve.perry@makotoconsulting.com
author1-email-cc=