Main Content

Tokens en expresiones regulares

Introducción

Los paréntesis que se utilizan en una expresión regular no solo agrupan los elementos de dicha expresión, sino que también designan cualquier coincidencia que se encuentra para ese grupo como token. Puede utilizar tokens para hacer que otras partes del mismo texto coincidan. Una ventaja de utilizar tokens es que recuerdan la coincidencia, de modo que puede recuperar y reutilizar el texto que ha coincidido en el proceso de búsqueda o sustitución.

Cada token de la expresión se asigna a un número comenzando desde el uno de izquierda a derecha. Para hacer referencia a un token más adelante en la expresión, haga referencia al token utilizando una barra invertida seguida del número del token. Por ejemplo, al hacer referencia a un token generado por el tercer conjunto de paréntesis de la expresión, utilice \3.

Como ejemplo simple, si desea buscar letras consecutivas idénticas en un arreglo de caracteres, podría capturar la primera letra como un token y buscar un carácter que coincida inmediatamente después. En la expresión que se muestra a continuación, la frase (\S) crea un token siempre que regexp coincida con cualquier carácter del arreglo de caracteres que no sea un espacio en blanco. La segunda parte de la expresión, '\1', busca una segunda instancia del mismo carácter inmediatamente después del primero.

poe = ['While I nodded, nearly napping, ' ...
       'suddenly there came a tapping,'];

[mat,tok,ext] = regexp(poe, '(\S)\1', 'match', ...
               'tokens', 'tokenExtents');
mat
mat =

  1×4 cell array

    {'dd'}    {'pp'}    {'dd'}    {'pp'}

El arreglo de celdas tok contiene arreglos de celdas que tienen un token.

tok{:}
ans =

  1×1 cell array

    {'d'}


ans =

  1×1 cell array

    {'p'}


ans =

  1×1 cell array

    {'d'}


ans =

  1×1 cell array

    {'p'}

El arreglo de celdas ext contiene arreglos numéricos que contienen índices de inicio y final para un token.

ext{:}
ans =

    11    11


ans =

    26    26


ans =

    35    35


ans =

    57    57

En otro ejemplo, capture pares de etiquetas HTML que coinciden (p. ej. <a> y </a>) y el texto que se encuentra entre ellas. La expresión utilizada para este ejemplo es

expr = '<(\w+).*?>.*?</\1>';

La primera parte de la expresión, '<(\w+)', coincide con una comilla angular de apertura (<) seguida de uno o más caracteres alfabéticos, numéricos o de guiones bajos. Los paréntesis capturan los caracteres de token que siguen a la comilla angular de apertura.

La segunda parte de la expresión, '.*?>.*?', coincide con el resto de esta etiqueta HTML (caracteres hasta >) y cualquier carácter que pueda preceder a la siguiente comilla angular de apertura.

La última parte, '</\1>', coincide con todos los caracteres de la etiqueta HTML final. Esta etiqueta está compuesta por la secuencia </tag>, en la que tag es cualquier carácter que se ha capturado como token.

hstr = '<!comment><a name="752507"></a><b>Default</b><br>';
expr = '<(\w+).*?>.*?</\1>';

[mat,tok] = regexp(hstr, expr, 'match', 'tokens');
mat{:}
ans =

    '<a name="752507"></a>'


ans =

    '<b>Default</b>'
tok{:}
ans =

  1×1 cell array

    {'a'}


ans =

  1×1 cell array

    {'b'}

Varios tokens

Este es un ejemplo de cómo se asignan valores a los tokens. Supongamos que va a buscar el siguiente texto:

andy ted bob jim andrew andy ted mark

Elige buscar el texto anterior con el siguiente patrón de búsqueda:

and(y|rew)|(t)e(d)

Este patrón tiene tres expresiones entre paréntesis que generan tokens. Cuando realiza la búsqueda, se generan los siguientes tokens para cada coincidencia.

Coincidencia

Token 1

Token 2

andy

y

 

ted

t

d

andrew

rew

 

andy

y

 

ted

t

d

Solo se utilizan los paréntesis de mayor nivel. Por ejemplo, si el patrón de búsqueda and(y|rew) encuentra el texto andrew, el valor rew se asigna al token 1. Sin embargo, si se utiliza el patrón de búsqueda (and(y|rew)), el valor andrew se asigna al token 1.

Tokens sin coincidencia

Para los tokens que se especifican en la expresión regular y que no tienen una coincidencia en el texto que se está evaluando, regexp y regexpi devuelven un vector de caracteres vacío ('') como la salida del token y una extensión que marca la posición de la cadena en la que se esperaba que estuviera el token.

En el ejemplo que se muestra a continuación se ejecuta regexp en un vector de caracteres especificando la ruta devuelta desde la función tempdir de MATLAB®. La expresión regular expr incluye seis especificadores de token, uno para cada parte de la ruta. El tercer especificador [a-z]+ no tiene ninguna coincidencia en el vector de caracteres porque esta parte de la ruta, Profiles, comienza por una letra en mayúscula:

chr = tempdir
chr =

    'C:\WINNT\Profiles\bpascal\LOCALS~1\Temp\'
expr = ['([A-Z]:)\\(WINNT)\\([a-z]+)?.*\\' ...
        '([a-z]+)\\([A-Z]+~\d)\\(Temp)\\'];

[tok, ext] = regexp(chr, expr, 'tokens', 'tokenExtents');

Cuando no se encuentra un token en el texto, regexp devuelve un vector de caracteres vacío ('') como el token y un arreglo numérico con la extensión del token. El primer número de la extensión es el índice de la cadena que marca el lugar en el que se esperaba que estuviera el token y el segundo número de la extensión es igual a uno menos que el primero.

En este ejemplo, el token vacío es el tercero especificado en la expresión, de modo que el tercer token que se devuelve está vacío:

tok{:}
ans =

  1×6 cell array

    {'C:'}    {'WINNT'}    {0×0 char}    {'bpascal'}    {'LOCALS~1'}    {'Temp'}

La extensión del tercer token que se devuelve en la variable ext tiene el índice de inicio establecido en 10, que es el lugar en el que el término no coincidente, Profiles, comienza en la ruta. El índice de extensión final se establece en uno menos que el índice de inicio o 9:

ext{:}
ans =

     1     2
     4     8
    10     9
    19    25
    27    34
    36    39

Tokens en texto de sustitución

Cuando utilice tokens en un texto de sustitución, haga referencia a ellos utilizando $1, $2, etc. en lugar de \1, \2, etc. Este ejemplo captura dos tokens e invierte su orden. El primero, $1, es 'Norma Jean' y el segundo, $2, es 'Baker'. Tenga en cuenta que regexprep devuelve el texto modificado, no un vector de índices de inicio.

regexprep('Norma Jean Baker', '(\w+\s\w+)\s(\w+)', '$2, $1')
ans =

    'Baker, Norma Jean'

Captura denominada

Si utiliza muchos tokens en las expresiones, puede ser útil asignarles nombres en lugar de tener que llevar un registro de qué número de token se le asigna a cada token.

Cuando haga referencia a un token denominado en la expresión, utilice la sintaxis \k<name> en lugar del valor numérico \1, \2, etc.:

poe = ['While I nodded, nearly napping, ' ...
       'suddenly there came a tapping,'];

regexp(poe, '(?<anychar>.)\k<anychar>', 'match')
ans =

  1×4 cell array

    {'dd'}    {'pp'}    {'dd'}    {'pp'}

Los tokens denominados también pueden ser útiles a la hora de etiquetar la salida de las funciones de expresiones regulares de MATLAB. Esto es particularmente cierto cuando procesa muchas partes de un texto.

Por ejemplo, analice diferentes partes de direcciones de calles de varios vectores de caracteres. Se asigna un nombre corto a cada token de la expresión:

chr1 = '134 Main Street, Boulder, CO, 14923';
chr2 = '26 Walnut Road, Topeka, KA, 25384';
chr3 = '847 Industrial Drive, Elizabeth, NJ, 73548';

p1 = '(?<adrs>\d+\s\S+\s(Road|Street|Avenue|Drive))';
p2 = '(?<city>[A-Z][a-z]+)';
p3 = '(?<state>[A-Z]{2})';
p4 = '(?<zip>\d{5})';

expr = [p1 ', ' p2 ', ' p3 ', ' p4];

Como demuestran los resultados que se muestran a continuación, puede hacer que sea más fácil trabajar con la salida utilizando tokens denominados:

loc1 = regexp(chr1, expr, 'names')
loc1 = 

  struct with fields:

     adrs: '134 Main Street'
     city: 'Boulder'
    state: 'CO'
      zip: '14923'
loc2 = regexp(chr2, expr, 'names')
loc2 = 

  struct with fields:

     adrs: '26 Walnut Road'
     city: 'Topeka'
    state: 'KA'
      zip: '25384'
loc3 = regexp(chr3, expr, 'names')
loc3 = 

  struct with fields:

     adrs: '847 Industrial Drive'
     city: 'Elizabeth'
    state: 'NJ'
      zip: '73548'

Consulte también

| |

Temas relacionados