• Publicidad

Expresión regular control edades

¿Ya sabes lo que es una referencia? Has progresado, el nível básico es cosa del pasado y ahora estás listo para el siguiente nivel.

Expresión regular control edades

Notapor otorices » 2011-05-05 05:49 @284

Estoy teniendo problemas con una expresión regular que detecta las edades.

La idea es que si en el texto se encuentra el patrón "P X años", donde "X" es un número de 1 a 3 dígitos, y "P" es una palabra distinta a "hace", "durante" y "por".

Esta última parte es la que no consigo que funcione, no sé cómo indicar en la expresión regular que no aparezcan ninguna de esas 3 palabras. Lo he intentado con la siguiente expresión:

/\b(^(durante|hace|por)\s)([0-9]{1,3}[\s]años)\b/


Sé que el símbolo "^" indica el comienzo de una cadena, pero también se puede utilizar para la negación. El caso es que solo consigo usarlo como negación si está entre corchetes.

¡Gracias!
otorices
Perlero nuevo
Perlero nuevo
 
Mensajes: 41
Registrado: 2009-04-16 13:59 @624

Publicidad

Re: Expresión regular control edades

Notapor explorer » 2011-05-05 17:21 @765

El carácter '^' tiene dos significados según donde se use. O puede indicar un anclaje a principio de la cadena, o si está dentro de una clase de caracteres y es el primer carácter de la clase, negar el significado de la clase de caracteres.

Pero es que tu caso no es ninguno de estos dos casos. Lo que quieres es negar la presencia de unas cadenas delante de un patrón.

En teoría, cuando queremos que un patrón no no sea precedido por una cadena, solemos usar el patrón (?<!patrón) delante de él. Debería ser: (?<!hace|durante|por) \d{1,3} años?

Pero... no funciona. Más bien, saldrá un error, indicando que el patrón que hay que indicar antes debe ser de longitud fija, y no es así: son tres cadenas, cada uno de una longitud distinta. Y además, en forma de alternativas. No funciona porque debería ser una sola cadena fija.

La solución (la que he encontrado): dividir el problema en dos: primero buscamos el patrón general, y luego comprobamos que la palabra que precede al número no sea una de las prohibidas.

Esta es una forma de verlo:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. #!/usr/bin/perl
  2. use Modern::Perl;                       # somos modernos
  3. use utf8;                               # este programa está escrito en utf8
  4. use autodie;                            # es mejor morir que regresar con deshonor (proverbio Klingon)
  5.  
  6. use open ':utf8';                       # la codificación de los ficheros es en utf8
  7. use open ':std';                        # también en STDIN y STDOUT
  8.  
  9. my @pruebas = (
  10.     'Argumentario 77 years',
  11.     'Tiene 231 años',
  12.     'Posee 1 año',
  13.     'Dame 2 AÑOS',
  14.     'largo 2311 años',
  15.  
  16.     'hace 123 años',
  17.     'durante 999 años',
  18.     'por 2 años',
  19.  
  20.     'estuvo 29 años',
  21.     'reclamó 7 años',
  22.     'permaneció 4 años',
  23.     'PruebaáéíoúñÑdepalabralarga 8 años',
  24. );
  25.  
  26. for my $texto (@pruebas) {
  27.  
  28.     print "[$texto]:";
  29.  
  30. #    if (utf8::is_utf8($texto)) {
  31. #        print "[sí]:";
  32. #    }
  33. #    else {
  34. #        print "[no]:";
  35. #    }
  36.  
  37.     if ($texto =~ m{\b(?<palabra>[[:word:]]+)\s+(?<edad>\d{1,3})\s+años?}i) {
  38.  
  39.         if (lc($+{palabra}) ~~ [qw[hace durante por]]) {
  40.             say "ERROR1";
  41.         }
  42.         else {
  43.             say "[$+{palabra}][$+{edad}]";
  44.         }
  45.     }
  46.     else {
  47.         say "ERROR2";
  48.     }
  49. }
  50. __END__
  51. [Argumentario 77 years]:ERROR2
  52. [Tiene 231 años]:[Tiene][231]
  53. [Posee 1 año]:[Posee][1]
  54. [Dame 2 AÑOS]:[Dame][2]
  55. [largo 2311 años]:ERROR2
  56. [hace 123 años]:ERROR1
  57. [durante 999 años]:ERROR1
  58. [por 2 años]:ERROR1
  59. [estuvo 29 años]:[estuvo][29]
  60. [reclamó 7 años]:[reclamó][7]
  61. [permaneció 4 años]:[permaneció][4]
  62. [PruebaáéíoúñÑdepalabralarga 8 años]:[PruebaáéíoúñÑdepalabralarga][8]
Coloreado en 0.008 segundos, usando GeSHi 1.0.8.4
Y vemos que funciona: las líneas marcadas con ERROR1 son las que contiene las palabras malditas; las que tienen ERROR2, no siguen el formato buscado; el resto sí que son cadenas correctas a lo que buscamos.
JF^D Perl programming & Raku programming. Grupo en Telegram: https://t.me/Perl_ES
Avatar de Usuario
explorer
Administrador
Administrador
 
Mensajes: 14480
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España

Re: Expresión regular control edades

Notapor otorices » 2011-05-06 09:13 @426

Gracias por la respuesta. De todas formas, ¿no sería más sencillo con ésta expresión?

(?<!durante\s)(?<!hace\s)(?<!por\s)\b([0-9]{1,3}[\s]años)

A mí al menos me sirve.
otorices
Perlero nuevo
Perlero nuevo
 
Mensajes: 41
Registrado: 2009-04-16 13:59 @624

Re: Expresión regular control edades

Notapor explorer » 2011-05-06 12:37 @567

Es una solución muy buena. :)
JF^D Perl programming & Raku programming. Grupo en Telegram: https://t.me/Perl_ES
Avatar de Usuario
explorer
Administrador
Administrador
 
Mensajes: 14480
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España


Volver a Intermedio

¿Quién está conectado?

Usuarios navegando por este Foro: No hay usuarios registrados visitando el Foro y 11 invitados