Perl en Español

  1. Home
  2. Tutoriales
  3. Foro
  4. Artículos
  5. Donativos
  6. Publicidad
 

obtener un patrón que incluye \n

 
Publicar nuevo tema   Responder al tema    Foros de discusión -> Básico
Mensaje Sab Abr 01, 2006 4:44 pm
bartoldo
Perlero Nuevo
Perlero Nuevo
Registrado: 01 Abr 2006
Mensajes: 7
obtener un patrón que incluye \n Responder citando

hola, estuve leyendo los manuales, pero no se como resolverlo. Debo reconocer un patrón que puede abarcar mas de una línea del archivo ascii que leo, y sustituirlo por algo 'abc'. Ej.: reconocer las líneas que comiencen con "Aqui" y terminen con "." El contenido del archivo puede ser el siguiente:
1-Aqui cualquier cosa. Sigue otra horaciónaksldjflkñasjdfklñj.\n
2-Aqui la linea ocupa tres (3) lineas, este renglon, \n
3-este siguiente y\n
4-este otro también. \n


O sea, el patrón está 2 veces, pero la último vez que ocurre es entre las líneas 2 y 4. No he podido resolverlo usando expresiones regulares. Tengo problemas para que me reconozca el punto, aun cuando el patrón se encuentra en una misma línea. Este es el código:

Código:
                $patron = '(\s*\.*)'; 
                        while (<INFILE>)
         {
                             if (s/^Aqui$patron./abc/sm)
                                {print; }                             

         }

gracias por cualquier sugerencia, saludos
Mensaje Dom Abr 02, 2006 4:43 am
explorer
Moderador
Moderador
Registrado: 24 Jul 2005
Mensajes: 4125
Ubicación: Valladolid, España
Responder citando

El problema está en leer el fichero línea a línea.
Al leer una línea no tenemos la seguridad de que dentro de ella se encuentre el patrón entero que estamos buscando.
Tenemos dos soluciones:
O leemos el fichero entero a una variable escalar y a continuación hacemos un
Código:
$fichero =~ s/^Aqui.+?\./abc/gsm;
con lo que estamos buscando todas las líneas que empiezan (^) por Aqui seguidas por una serie de caracteres (un carácter (.) seguido por uno o más (+)) hasta el primer (?) punto (\.), y lo sustituímos por abc. Esto lo hacemos para una variable escalar con múltiples líneas (/m), incluídos los finales de línea (/s) y para todas las ocasiones (/g).
O, la otra solución, que consiste en leer línea por línea y llevar un control de lo que va ocurriendo. Por ejemplo.
Código:
Para todo el texto, leemos una línea cada vez
  Si la bandera está a 1 (estamos dentro de un patrón detectado)
    Si la línea tiene el final del patrón
      Ponemos la bandera a 0 y
      Hacemos la sustitución, la pintamos y seguimos con la siguiente línea
    Seguimos con la siguiente línea (aún seguimos dentro del patrón detectado)
  Si la línea contiene el comienzo y final del patrón,
    Hacemos la sustitución, la pintamos y seguimos con la siguiente línea
  Si la línea contiene el comienzo del patrón
    Ponemos la bandera a 1 (estamos dentro de un patrón pero no sabemos cuándo terminará) y
    Seguimos con la siguiente línea
  Si no ocurre nada de lo anterior, pintamos la línea tal cual
Es natural que la primera solución (una línea) es mejor... Smile

En tu caso:
Código:
$patron = '(\s*\.*)';
while (<INFILE>) {
    if (s/^Aqui$patron./abc/sm) {
        print;
    }
}
lo que haces es: Para todas las líneas del fichero (while), si (if) la línea puede realizar una sustitución del patrón, la pintamos (print), siendo el patrón a buscar: ^Aqui\s*\.*., que significa: la línea empieza (^) por Aqui, seguido de 0 o más espacios en blanco (\s*), seguidos de 0 o más puntos (\.*) y seguidos por un carácter cualquiera (.), para todas las líneas (/m) leídas (aunque me parece que sólo hemos leído una).

Ultima edición por explorer el Dom Abr 02, 2006 5:03 am, editado 3 veces
Mensaje Dom Abr 02, 2006 4:44 am
preiddy
Perlero Nuevo
Perlero Nuevo
Registrado: 29 Mar 2006
Mensajes: 50
Responder citando

explorer me dio una solución a un problema parecido al tuyo, quizas te sirva
Código:
while ( $base =~ /(^PT.+?^ER *?$)/smg )

con esta expresion se le dice principio y fin de campos, independientemente de cuantos saltos de linea tenga.
Mensaje Dom Abr 02, 2006 11:55 am
bartoldo
Perlero Nuevo
Perlero Nuevo
Registrado: 01 Abr 2006
Mensajes: 7
Responder citando

gente, voy a probar las sugerencias, luego les cuento. gracias
Mensaje Dom Abr 02, 2006 12:22 pm
bartoldo
Perlero Nuevo
Perlero Nuevo
Registrado: 01 Abr 2006
Mensajes: 7
Responder citando

bueno, el problema parece ser que no me reconoce el patrón, que recuerdo es toda frase que comience con la palabra "Aqui" y termina con ".", donde el "." no tiene porqué estar antes de un \n, puede estar en el medio de una línea. Ej: "Aqui estamos. Sin nada que hacer\n", la frase debería quedar:
abc Sin nada que hacer\n

Probé
Código:
 while ( $file =~ /^Aqui.*?\./smg )
                    {
                           print if s/^Aqui.*?\./abc/smg;
          }

Olímpicamente ignora el patrón.

Seguidamente probé la otra sugerencia:
Código:
$file =~ s/^Aqui.*?\./abc/smg;
#ignoró también, no hubo cambios

Creo que el tema está en reconocer el ".", porque si no lo considero en el patrón, encuentra las frases, solo que no sustituye lo que quiero. Seguiré intentando, desde ya les agradezco cualquier idea.
saludos
Mensaje Dom Abr 02, 2006 12:32 pm
explorer
Moderador
Moderador
Registrado: 24 Jul 2005
Mensajes: 4125
Ubicación: Valladolid, España
Responder citando

Supongamos que el fichero kk.txt sea
Código:
Aqui cualquier cosa. Sigue otra horaciónaksldjflkñasjdfklñj.
Aqui la linea ocupa tres (3) lineas, este renglon,
este siguiente y
este otro también.
Entonces, con el programa
Código:
#!/usr/bin/perl
open FILE, "<kk.txt";
while ( $linea = <FILE> ) {
  $fichero = $fichero . $linea;   # Leemos todas las líneas y las metemos en una variable
}
close FILE;
$fichero =~ s/^Aqui.+?\./abc/gsm; # Transmutación, ¡Aquí y Ahora!
print $fichero;
sale
Código:
abc Sigue otra horaciónaksldjflkñasjdfklñj.
abc
¿No es eso lo que tiene que salir?
Mensaje Dom Abr 02, 2006 7:14 pm
bartoldo
Perlero Nuevo
Perlero Nuevo
Registrado: 01 Abr 2006
Mensajes: 7
Responder citando

Es exactamente eso, funciona, gracias Smile
Publicar nuevo tema   Responder al tema    Foros de discusión -> Básico Todas las horas son GMT - 6 Horas
Página 1 de 1



Powered by phpBB © 2001, 2005 phpBB Group