Mar Jul 01, 2008 6:39 am
|
 |
STM
Perlero Nuevo

|
Registrado: 01 Jul 2008
Mensajes: 14
|
|
| Función grep |
|
|
Hola a todos
Desearía hacerles una pregunta:
1-) Tengo un archivo del cual debo escoger solo ciertas líneas, cada línea queda dividida en cinco partes y yo trabajo solo con tres: $ip1, $ip3, $ip6, así que escribí
| Perl: | open (IN, "BRA065.txt");
open(BRA, ">bra.txt");
foreach $bra (($ip1, $ip2, $ip3, $ip4, $ip5, $ip6) = split(" ", $_, 6)){
@bras= grep(/w/,/area/,/spc/, $cmos);
write BRA |
Uso la función grep para seleccionar las líneas que tienen cualquiera de las palabras spc, area o w para guardarlas en @bra pero él imprime la información contenida en $bra y no en @bra.
En realidad no sé cómo especificarle que imprima la información contenida en @bra
usando la función write (porque tengo un formato que respetar).
Muchas gracias de antemano a las personas que me puedan ayudar.
Hasta Luego. |
|
|
|

Mar Jul 01, 2008 6:57 am
|
 |
explorer
Moderador

|
Registrado: 24 Jul 2005
Mensajes: 3915
Ubicación: Valladolid, España
|
|
|
|
|
Bienvenido a los foros de Perl en Español, STM.
Andas un poco perdido con la sintaxis, me parece a mí...
En el comentario hablas de la función @bra, pero en el código pones @bras.
grep(), en el código, está analizando la variable $cmos de la cual no sabemos de dónde viene. Ni siquiera estás comparando los valores de las variables $ip1, $ip3, $ip6.
Y de la pobre variable $bra, no sabemos para qué la usas, porque solo aparece una vez en el código.
No está claro qué es lo que quieres guardar en @bra: ¿los campos extraídos por split() o toda la línea? |
|

Mar Jul 01, 2008 7:31 am
|
 |
STM
Perlero Nuevo

|
Registrado: 01 Jul 2008
Mensajes: 14
|
|
|
|
|
Hola,
lo siento, es que copié mal el código que tenía; el verdadero código es así:
| Perl: | open (IN, "BRA065.txt");
open(BRA, ">bra.txt");
foreach $bra (($ip1, $ip2, $ip3, $ip4, $ip5, $ip6) = split(" ", $_, 6)){
@bra= grep(/w/,/area/,/spc/, $bra);
write BRA |
Muchas Gracias |
|

Mar Jul 01, 2008 7:46 am
|
 |
explorer
Moderador

|
Registrado: 24 Jul 2005
Mensajes: 3915
Ubicación: Valladolid, España
|
|
|
|
|
Siguen faltando muchas pistas, pero una primera aproximación al problema podría ser | Perl: | open (IN, "BRA065.txt");
open(BRA, ">bra.txt");
($ip1, $ip2, $ip3, $ip4, $ip5, $ip6) = split;
@bra = grep { /w|area|spc/ } $ip1, $ip3, $ip6;
write BRA |
* La línea ($_) que se supone que estará compuesta de campos separados por espacios en blanco, es dividida y nos quedamos con las 6 primeras partes
* Las partes que nos interesan entran en el grep y son filtrados por la expresión regular, que busca patrones de 'w', 'area' o 'spc'. Si alguno coincide, se van almacenando en @bra
* Y luego escribe el resultado, pero no sabemos qué aspecto tiene el formato para write(), así que eso ya depende de ti.
Se pueden abreviar las dos líneas en una:
| Perl: | @bra = grep { /w|area|spc/ } ( split )[0, 2, 5]; |
|
|

Mie Jul 02, 2008 2:07 am
|
 |
STM
Perlero Nuevo

|
Registrado: 01 Jul 2008
Mensajes: 14
|
|
|
|
|
Hola de nuevo,
Ya ensaye el código que usted me envió pero él continúa imprimiendo todas las líneas del archivo original.
Esta vez envío el código completo de mi programa (no es muy grande, pero ya no es el mismo que yo tenía ayer). Ensayé varias sintaxis de la función grep pero nada funciona y no entiendo por qué.
| Perl: | open (IN, "BRA065.txt");
open(BRA, ">bra065.txt");
while (<IN>) {
chomp;
#while ($line=<IN>) {
#foreach $bra_1 (($ip1,$ip2,$ip3,$ip4,$ip5,$ip6) = split(" ", $_, 6)){
#@bra= grep{m/^[density_W, win, step, length, nalw]//}$bra_1;
#($ip1, $ip2, $ip3,$ip4,$ip5,$ip6) = split(" ", $_, 6);
#foreach $bra_1 (($ip1,$ip2,$ip3,$ip4,$ip5,$ip6) = split(" ", $_, 6)){
#@bra= grep{m/^[density_W, win, step, length, nalw]//}$bra_1;
if (@bra eq "OD.W.1")
{@bra= OD.WIDTH }
if (@bra eq "OD.S.1")
{@bra= OD.SPACE }
#@bra = grep { /w|area|spc/ } ( split )[0,3,4];
($ip1, $ip2, $ip3, $ip4, $ip5, $ip6) = split;
@bra = grep { /w|area|spc/ } $ip1, $ip4, $ip5;
write BRA ; #"$bra\n"; #print bra
}
format BRA =
@<<<<<<< ( @<<<<<<< @<<<<<< )
$ip1, $ip4, $ip5
.
#"$bra\n"; #print bra
} |
Muchas gracias de antemano por su ayuda. |
|

Mie Jul 02, 2008 5:21 am
|
 |
explorer
Moderador

|
Registrado: 24 Jul 2005
Mensajes: 3915
Ubicación: Valladolid, España
|
|
|
|
|
Si estás empezando con Perl, es muy recomendable que pongas
al principio del programa. Te avisará de cosas extrañas que pones en tu código.
Por ejemplo, las líneas | Perl: | if (@bra eq "OD.W.1")
{@bra= OD.WIDTH}
if (@bra eq "OD.S.1")
{@bra= OD.SPACE} |
no tienen mucho sentido para mí. ¿Dónde se inicializa la variable @bra? ¿Qué valor devuelve la función OD.WIDTH? ¿Dónde está definida? Lo mismo para la función OD.SPACE.
Es más... estás intentando comparar un array con una cadena de caracteres:
| Perl: | if (@bra eq "OD.W.1") | lo cual tampoco tiene mucho sentido (salvo que estés usando Perl5.10, pero en ese caso no estás usando el operador smart-match).
Para evitar que te muestre todas las líneas del fichero, te falta por saber qué líneas son las que quieres imprimir. Eso implica hacer una condición, que suponemos que es la que quieres hacer con el comando grep().
Esta es una opción (no probada):
| Perl: | #!/usr/bin/perl
use strict;
use warnings;
# Nuestras variables
my ($ip1, $ip4, $ip5);
# Abrimos los ficheros
open (IN, "<BRA065.txt") or die "$!\n";
open (BRA, ">bra065.txt") or die "$!\n";
# Definimos el formato
format BRA =
@<<<<<<< ( @<<<<<<< @<<<<<< )
$ip1, $ip4, $ip5
.
# Para todo el fichero
while ( <IN> ) { # Leemos la línea
($ip1, undef,undef, $ip4, $ip5, undef) = split; # La partimos
if ( grep { /w|area|spc/ } $ip1, $ip4, $ip5 ) { # Si tenemos algo realmente interesante
write BRA; # Lo imprimimos
}
}
# Cerramos los ficheros
close IN;
close BRA; | Ya te digo que no lo he podido probar, sobre todo porque no sé muy bien como es el fichero de entrada y qué es lo que quieres sacar/filtrar, ya que los if que has puesto ahora me han despistado. |
|

Mie Jul 02, 2008 6:57 am
|
 |
STM
Perlero Nuevo

|
Registrado: 01 Jul 2008
Mensajes: 14
|
|
| Funcion grep |
|
|
Buenas Tardes,
Pues yo creía que el programa funcionaba de la siguiente forma:
Las variables ipXXXX se inicializan con la primera línea leída en el archivo BRA.txt y van cambiando continuamente de datos hasta que se termina de leer el archivo.
La idea es que yo debo leer el archivo, filtrar las líneas donde aparecen las palabras (w, area, spc) y guardarlas en el nuevo archivo bra.txt.
Con el if, yo pensaba hacer un reemplazo de datos porque hay líneas que tienen la frase OD.W.1 y yo quisiera que en el nuevo archivo esa frase quede OD.WIDTH (OD.W.1 no es una función, es una cadena de caracteres lo mismo que OD.SPACE).
Siento mucho molestar tanto.
Muchas Gracias.  |
|

Mie Jul 02, 2008 7:31 am
|
 |
explorer
Moderador

|
Registrado: 24 Jul 2005
Mensajes: 3915
Ubicación: Valladolid, España
|
|
|
|
|
Entiendo lo del reemplazo, que puedes hacer así:
| Perl: | s/OD\.W\. 1/OD.WIDTH/g;
s/OD\.S\. 1/OD.SPACE/g; |
Con eso modificarás la variable $_, que contiene la línea que has leído en el while.
Ahora bien... ¿por qué hacer este reemplazo? En el fichero de salida van a salir 3 columnas, con los valores de los campos 1 4 y 5. Si en alguno de ellos aparecen los patrones (w, area o spc) (escritas así, en minúscula) entonces los graba. Pero si no, no.
Vamos, que no entiendo qué relación puede haber entre querer hacer un reemplazo, si ese reemplazo no va a salir en el fichero. ¿O es que sí debería salir? En ese caso, no está del todo explicado qué líneas son las que deseamos sacar fuera.
P.D.1: No es buena idea que los dos ficheros se llamen casi igual.
P.D.2:
Aquí nadie molesta, porque el que molesta, no está aquí. |
|

Mie Jul 02, 2008 7:47 am
|
 |
STM
Perlero Nuevo

|
Registrado: 01 Jul 2008
Mensajes: 14
|
|
|
|
|
Buenas tardes.
Mi idea es que el remplazo se vea en el segundo archivo.
En realidad yo deseo hacer algo así:
yo leo el archivo de entrada, filtro las líneas donde aparece " w,spc,area" .
Como cada línea está dividida en seis tomo solo tres partes, las acomodo según mi formato y hago el reemplazo.
Al final tendré un archivo de tres columnas que en vez de tener w tendrá width y así sucesivamente con spc y area.
Muchas Gracias. |
|

Mie Jul 02, 2008 8:12 am
|
 |
explorer
Moderador

|
Registrado: 24 Jul 2005
Mensajes: 3915
Ubicación: Valladolid, España
|
|
|
|
|
¡Ah! Pero es que eso cambia mucho la cosa...
| Perl: | #!/usr/bin/perl
use strict;
use warnings;
# Nuestras variables
my ($ip1, $ip4, $ip5);
# Abrimos los ficheros
open (IN, "<BRA065.txt") or die "$!\n";
open (BRA, ">bra065.txt") or die "$!\n";
# Definimos el formato
format BRA =
@<<<<<<< ( @<<<<<<< @<<<<<< )
$ip1, $ip4, $ip5
.
# Yo leo el archivo de entrada,
while ( <IN> ) {
# Filtro las líneas donde aparece "w,spc,area"
if ( /w|area|spc/i ) {
# hago el reemplazo
s/OD\.W\. 1/OD.WIDTH/g;
s/OD\.S\. 1/OD.SPACE/g;
# Como cada línea está dividida en seis tomo solo tres partes
($ip1, undef,undef, $ip4, $ip5, undef) = split;
# las acomodo según mi formato
write BRA;
}
}
# Cerramos los ficheros
close IN;
close BRA; |
Como ves, tu mismo has dado la solución al problema, salvo un detalle: había que hacer el reemplazo ANTES de hacer la división de la línea. Si lo hubiéramos hecho al revés, tendríamos que haber hecho el reemplazo por cada una de las 3 partes. Mejor hacerlo solo una vez. |
|

Mie Jul 02, 2008 8:48 am
|
 |
STM
Perlero Nuevo

|
Registrado: 01 Jul 2008
Mensajes: 14
|
|
|
|
|
Muchas Gracias.
Muy amable, al fin entiendo.
Ahora podré adicionar e implementar más funciones.
Hasta Luego. |
|
Mie Jul 02, 2008 9:57 am
|
 |
STM
Perlero Nuevo

|
Registrado: 01 Jul 2008
Mensajes: 14
|
|
|
|
|
Buenas Tardes.
He estado trabajando en el código pero resulta que le añadí más líneas al archivo fuente BRA.txt y ahora solo filtra las primeras líneas pero después deja pasar todo; en el archivo de salida uno obtiene una copia exacta del archivo de entrada; yo creo que es porque aparece el símbolo "#" y espacios en blanco al principio de algunas de las líneas del archivo de entrada.
¿Es que debo trabajar con if anidados?
Porque pareciera que él hace un buen filtraje hasta la parte donde encuentra un símbolo raro (algo diferente a una letra).
Muchas gracias. |
|

Mie Jul 02, 2008 3:11 pm
|
 |
explorer
Moderador

|
Registrado: 24 Jul 2005
Mensajes: 3915
Ubicación: Valladolid, España
|
|
|
|
|
El programa está perfecto para el caso de que el fichero de entrada conste de líneas con 6 o más campos de texto separados con espacios en blanco.
Si las líneas del fichero no siguen esa sencilla regla, entonces, split, falla.
Si cambias las condiciones del juego, debes cambiar las reglas del juego. O no hay juego. |
|
Mie Jul 02, 2008 3:33 pm
|
 |
explorer
Moderador

|
Registrado: 24 Jul 2005
Mensajes: 3915
Ubicación: Valladolid, España
|
|
|
|
|
| STM escribió: | | yo creo que es porque aparece el símbolo "#" y espacios en blanco al principio de algunas de las líneas del archivo de entrada. |
Si quieres filtrar esas líneas, puedes colocar
después del while. |
|
Jue Jul 03, 2008 8:55 am
|
 |
STM
Perlero Nuevo

|
Registrado: 01 Jul 2008
Mensajes: 14
|
|
| Seleccion |
|
|
Hola, Buen día.
He visto que existen expresiones que detectan un carácter y lo eliminan, pero ¿si lo que se necesita es eliminar todas las palabras que contengan ese carácter? porque yo intenté esto: | Perl: | s/ lenght/ /g;
next if /^ #/;
next if /^$/; | pero estas expresiones sirven para comparar una palabra dada, no un carácter.
Pero yo lo que deseo es detectar el carácter "<" y eliminar toda la línea.
Muchas gracias de antemano.
Hasta Luego |
|
Powered by phpBB © 2001, 2005 phpBB Group
|