Ejemplo de expresiones regulares: Analizador Wiki

Flash Player 9 y posterior, Adobe AIR 1.0 y posterior

Este ejemplo simple de conversión de texto de Wiki ilustra diversos usos de las expresiones regulares:

  • Convertir líneas de texto que coinciden con un patrón de Wiki de origen con las cadenas HTML de salida apropiadas.

  • Utilizar una expresión regular para convertir patrones de URL en etiquetas de hipervínculos HTML <a>.

  • Usar una expresión regular para convertir cadenas con valores monetarios en dólares de EE.UU. (como "$9,95") en cadenas que contienen valores monetarios en euros (como "8,24 €").

Para obtener los archivos de la aplicación de este ejemplo, consulte www.adobe.com/go/learn_programmingAS3samples_flash_es. Los archivos de la aplicación WikiEditor se encuentran en la carpeta Samples/WikiEditor. La aplicación consta de los siguientes archivos:

Archivo

Descripción

WikiEditor.mxml

o

WikiEditor.fla

El archivo de aplicación principal en Flash (FLA) o Flex (MXML).

com/example/programmingas3/regExpExamples/WikiParser.as

Una clase que incluye métodos que utilizan expresiones regulares para convertir patrones de texto de Wiki de origen en la salida HTML equivalente.

com/example/programmingas3/regExpExamples/URLParser.as

Una clase que incluye métodos que utilizan expresiones regulares para convertir cadenas de URL en etiquetas de hipervínculos HTML <a>.

com/example/programmingas3/regExpExamples/CurrencyConverter.as

Una clase que incluye métodos que utilizan expresiones regulares para convertir cadenas con valores monetarios en dólares de EE.UU. en cadenas en euros.

Definición de la clase WikiParser

La clase WikiParser incluye métodos que convierten texto Wiki de entrada en la salida HTML equivalente. Esta aplicación de conversión de Wiki no es muy sólida, pero ilustra algunos usos útiles de las expresiones regulares para la detección de patrones y la conversión de cadenas.

La función constructora, junto con el método setWikiData(), simplemente inicializa una cadena de ejemplo de texto de entrada de Wiki, de la manera siguiente:

public function WikiParser() 
{ 
    wikiData = setWikiData(); 
}

Cuando el usuario hace clic en el botón Test de la aplicación de ejemplo, la aplicación invoca al método parseWikiString() del objeto WikiParser. Este método llama a otros métodos, que a su vez crean la cadena HTML resultante.

public function parseWikiString(wikiString:String):String 
{ 
    var result:String = parseBold(wikiString); 
    result = parseItalic(result); 
    result = linesToParagraphs(result); 
    result = parseBullets(result); 
    return result; 
}

Cada uno de los métodos llamados, parseBold(), parseItalic(), linesToParagraphs() y parseBullets() utiliza el método replace() de la cadena para sustituir patrones coincidentes, definidos por una expresión regular, a fin de transformar el texto de entrada del Wiki en texto con formato HTML.

Conversión de patrones en negrita y en cursiva

El método parseBold() busca un patrón de texto de Wiki en negrita (como '''foo''') y lo transforma en su equivalente HTML (como <b>foo</b>), de la manera siguiente:

private function parseBold(input:String):String 
{ 
    var pattern:RegExp = /'''(.*?)'''/g; 
    return input.replace(pattern, "<b>$1</b>"); 
}

Hay que tener en cuenta que la parte (.?*) de la expresión regular detecta un número arbitrario de caracteres (*) entre los dos patrones delimitadores'''. El cuantificador ? hace que no se detecte la mayor cantidad posible de caracteres, de forma que para una cadena como '''aaa''' bbb '''ccc''', la primera cadena detectada será '''aaa''' y no la cadena completa (que empieza y termina con el patrón ''').

Los paréntesis de la expresión regular definen un grupo de captura y el método replace() hace referencia a este grupo mediante el código $1 en la cadena de sustitución. El indicador g (global) de la expresión regular garantiza que el método replace() sustituye todas las coincidencias de la cadena (no solo la primera).

El método parseItalic() funciona de forma similar al método parseBold(), con la diferencia de que busca dos apóstrofes (''), no tres, como delimitador del texto en cursiva:

private function parseItalic(input:String):String 
{ 
    var pattern:RegExp = /''(.*?)''/g; 
    return input.replace(pattern, "<i>$1</i>"); 
}

Conversión de patrones de viñetas

Como se indica en el siguiente ejemplo, el método parseBullet() busca el patrón de línea de viñeta del Wiki (como * foo) y la transforma en su equivalente HTML (como <li>foo</li>):

private function parseBullets(input:String):String 
{ 
    var pattern:RegExp = /^\*(.*)/gm; 
    return input.replace(pattern, "<li>$1</li>"); 
}

El símbolo ^ al principio de la expresión regular detecta el principio de una línea. El indicador m (multiline) de la expresión regular hace que la expresión regular detecte el símbolo ^ en cada principio de línea, no solo al principio de la cadena.

El patrón \* detecta un asterisco (se utiliza la barra diagonal inversa para indicar un asterisco literal en lugar del cuantificador *).

Los paréntesis de la expresión regular definen un grupo de captura y el método replace() hace referencia a este grupo mediante el código $1 en la cadena de sustitución. El indicador g (global) de la expresión regular garantiza que el método replace() sustituye todas las coincidencias de la cadena (no solo la primera).

Conversión de patrones de párrafo de Wiki

El método linesToParagraphs() convierte cada línea de la cadena de entrada de Wiki en una etiqueta de párrafo HTML, <p>. Estas líneas del método eliminan las líneas vacías de la cadena de Wiki de entrada:

var pattern:RegExp = /^$/gm; 
var result:String = input.replace(pattern, "");

Los símbolos ^ y $ hacen que la expresión regular detecte el principio y el final de una línea. El indicador m (multiline) de la expresión regular hace que la expresión regular detecte el símbolo ^ en cada principio de línea, no solo al principio de la cadena.

El método replace() sustituye todas las subcadenas coincidentes (líneas vacías) con una cadena vacía (""). El indicador g (global) de la expresión regular garantiza que el método replace() sustituye todas las coincidencias de la cadena (no solo la primera).

Conversión de direcciones URL en etiquetas HTML <a>

Cuando el usuario hace clic en el botón Test en la aplicación de ejemplo, si seleccionó la casilla de verificación urlToATag, la aplicación llama al método estático URLParser.urlToATag() para convertir cadenas de dirección URL de la cadena de Wiki de entrada en etiquetas HTML <a>.

var protocol:String = "((?:http|ftp)://)"; 
var urlPart:String = "([a-z0-9_-]+\.[a-z0-9_-]+)"; 
var optionalUrlPart:String = "(\.[a-z0-9_-]*)"; 
var urlPattern:RegExp = new RegExp(protocol + urlPart + optionalUrlPart, "ig"); 
var result:String = input.replace(urlPattern, "<a href='$1$2$3'><u>$1$2$3</u></a>");

La función constructora RegExp() se utiliza para crear una expresión regular (urlPattern) a partir de varios constituyentes. Estos constituyentes son cadenas que definen partes del patrón de la expresión regular.

La primera parte del patrón de la expresión regular, definida por la cadena protocol, define un protocolo de URL: http:// o ftp://. Los paréntesis definen un grupo que no captura, indicado por el símbolo ?. Esto significa que los paréntesis se utilizan simplemente para definir un grupo para el patrón de alternancia|; el grupo no detectará códigos de elementos detectados previamente ($1, $2, $3) en la cadena de sustitución del método replace().

Los otros elementos constituyentes de la expresión regular utilizan grupos de captura (indicados mediante paréntesis en el patrón), que se utilizan en los códigos de referencia a elementos detectados previamente ($1, $2, $3) en la cadena de sustitución del método replace().

La parte del patrón definida por la cadena urlPart detecta al menos uno de los siguientes caracteres: a-z, 0-9, _ o -. El cuantificador + indica que debe detectarse al menos un carácter. \. indica un carácter punto (.) requerido. Y el resto detecta otra cadena que conste al menos de uno de los siguientes caracteres: a-z, 0-9, _ o -.

La parte del patrón definida por la cadena optionalUrlPart detecta cero o más de los caracteres siguientes: un punto (. seguido de cualquier número de caracteres alfanuméricos (incluidos _ y -. El cuantificador * indica que deben detectarse cero o más caracteres.

La llamada al método replace() utiliza la expresión regular y crea la cadena HTML de sustitución utilizando referencias a elementos detectados previamente.

A continuación, el método urlToATag() llama al método emailToATag(), que utiliza técnicas similares para sustituir patrones de correo electrónico por cadenas de hipervínculos HTML <a>. Las expresiones regulares utilizadas para detectar direcciones URL HTTP, FTP y de correo electrónico en este archivo son bastante sencillas (para los fines del ejemplo); hay expresiones regulares mucho más complicadas para detectar direcciones URL de forma correcta.

Conversión de cadenas con valores monetarios en dólares de EE.UU. en cadenas con valores monetarios en euros

Cuando el usuario hace clic en el botón Test de la aplicación de ejemplo, si activó la casilla de verificación dollarToEuro, la aplicación llama al método estático CurrencyConverter.usdToEuro() para convertir cadenas con valores monetarios en dólares de EE.UU. (como "$9.95") en cadenas con valores monetarios en euros (como "8.24€"), de la manera siguiente:

var usdPrice:RegExp = /\$([\d,]+.\d+)+/g; 
return input.replace(usdPrice, usdStrToEuroStr); 

La primera línea define un patrón sencillo para detectar cadenas con valores monetarios en dólares de EE.UU. Obsérvese que antes del carácter $ se escribe una barra diagonal inversa de escape (\).

El método replace() utiliza la expresión regular como detector de patrones y llama a la función usdStrToEuroStr() para determinar la cadena de sustitución (un valor en euros).

Cuando se utiliza un nombre de función como segundo parámetro del método replace(), se pasan a la función llamada los parámetros siguientes:

  • La parte coincidente de la cadena.

  • Las coincidencias detectadas por grupos de paréntesis de captura. El número de argumentos pasados de esta forma varía en función del número de capturas de grupos entre paréntesis. Se puede determinar el número de capturas de grupos entre paréntesis comprobando arguments.length - 3 dentro del código de la función.

  • La posición de índice en la que comienza la coincidencia en la cadena.

  • La cadena completa.

El método usdStrToEuroStr() convierte patrones de cadena con valores monetarios en dólares de EE.UU. en cadenas con valores monetarios en euros, de la manera siguiente:

private function usdToEuro(...args):String 
{ 
    var usd:String = args[1]; 
    usd = usd.replace(",", ""); 
    var exchangeRate:Number = 0.828017; 
    var euro:Number = Number(usd) * exchangeRate; 
    trace(usd, Number(usd), euro); 
    const euroSymbol:String = String.fromCharCode(8364); // € 
    return euro.toFixed(2) + " " + euroSymbol;  
}

Hay que tener en cuenta que args[1] representa la captura de grupo entre paréntesis detectada por la expresión regular usdPrice. Esta es la parte numérica de la cadena de dólares de EE.UU., es decir, la cantidad de dólares sin el símbolo $. El método aplica una conversión de tasa de cambio y devuelve la cadena resultante (con un símbolo € final, en lugar de un símbolo $ inicial).