Jue Jul 24, 2008 9:43 am
|
 |
Zeokat
Perlero Frecuente

|
Registrado: 22 Ago 2006
Mensajes: 115
|
|
| Extraer palabras segun un patrón |
|
|
Me explico, tengo varias líneas en un fichero de la siguiente forma.
13caracteres:defaultnombre
De forma que una línea podría ser así:
13caracteres:defaultnombre213caracteres:defaultnombre113caracteres:defaultnombre0
Yo tengo que extraer las palabras y guardarlas en otro archivo de forma que en el archivo de salida se almacenen así:
| Código: |
nombre0:13carateres
nombre1:13carateres
nombre2:13carateres |
Teniendo en cuenta que a nombrex le corresponden los 13 caracteres que tiene a su izquierda después de la palabra default.
También como se podría pensar, la línea siempre empieza por 13caracteres, pero a veces no es así. Por lo que yo tenía pensado buscar el último "default" de cada línea, leer los caracteres que están a su derecha (nombrex) y luego contar 14 caracteres a partir del "default" y almacenar los últimos 13 (ya que el carácter ':' no hace falta).
También tener en cuanta que los 13caracteres, no es una palabra siempre igual de 13 caracteres, sino que son 13 caracteres aleatorios.
La verdad es que no consigo abordar el problema, a ver si a alguien se le ocurre alguna idea. Quizás haya una manera más sencilla.
Gracias de antemano.  |
|
|
|

Jue Jul 24, 2008 12:46 pm
|
 |
Zeokat
Perlero Frecuente

|
Registrado: 22 Ago 2006
Mensajes: 115
|
|
|
|
|
Lo probé en un archivo sencillo y parece funcionar:
| Perl: | #!/usr/bin/perl -w
use strict;
my $dhd_file = $ARGV[0];
chomp($dhd_file);
open DATABASE, "$dhd_file" or die "The specified file cant be located.... \n";
my @database = <DATABASE>;
close(DATABASE );
my @valid_line;
foreach my $line (@database) {
if ($line =~ /:default/ ) {
push (@valid_line, $line);
}
}
foreach my $line (@valid_line) {
while (length($line) >= 14 && $line =~ /:default/ ) {
chomp($line);
my $posicion = rindex($line, ":default");
my @test = split(//, $line);
my $posicion2 = scalar(@test);
my $str = substr($line, $posicion- 13, $posicion2);
print $str, "\n";
$line =~ s/ $str//;
}
} |
El problema es cuando hay un carácter especial, por ejemplo
Se queda ahí hasta Out of memory... No sé cómo solucionarlo tampoco. |
|

Jue Jul 24, 2008 2:40 pm
|
 |
explorer
Moderador

|
Registrado: 24 Jul 2005
Mensajes: 3841
Ubicación: Valladolid, España
|
|
|
|
|
A mí me faltan algunos detalles...
¿De qué longitud son los nombres?
Dices que no siempre empieza por '13caracteres', entonces, en ese caso, ¿empieza por 'default' o por un nombre? |
|
Vie Jul 25, 2008 4:36 am
|
 |
Zeokat
Perlero Frecuente

|
Registrado: 22 Ago 2006
Mensajes: 115
|
|
|
|
|
Los nombres pueden variar su longitud, pero siempre tendrá como mínimo un carácter.
| Cita: | | Dices que no siempre empieza por '13caracteres', entonces, en ese caso, ¿empieza por 'default' o por un nombre? |
Me refería a que a veces no empieza por 13caracteres sino que a veces, por propio error en el archivo que estoy tratando algo ha salido mal (ajeno a mí) y empieza por una palabra que tiene menos de 13 caracteres. |
|

Vie Jul 25, 2008 6:12 am
|
 |
explorer
Moderador

|
Registrado: 24 Jul 2005
Mensajes: 3841
Ubicación: Valladolid, España
|
|
|
|
|
Esta es mi solución.
| Perl: | #!/usr/bin/perl
use strict;
use warnings;
use diagnostics;
while ( <DATA> ) {
while (
/ # Comienza la expresión regular
( # Capturamos ...
^ \w {1, 12} # aquello que comienza la línea por menos de 13 caracteres
| # o
\w {13} # aquello que tiene 13 caracteres
) # ... como $1
:default # delante de un ':default'
( # capturamos ...
\w+ # un montón de caracteres
) # ... como $2
(?= # que precedan
$ # al fin de línea
| # o
\w {13} :default # a otro conjunto de 13 caracteres con un ':default'
) # Esto no lo capturamos ahora, pero sí la siguiente vuelta
/simogx # Fin de la expresión regular
) {
print "$2:$1\n"; # Pintamos lo capturado
}
}
__DATA__
13caracteres0:defaultnombre013caracteres0:defaultnombre113caracteres0:defaultnombre2
13caracteres1:defaultnombre3
13caracteres2:defaultnombre413caracteres2:defaultnombre5
13caracteres:defaultnombre6 |
Salida:
| Código: |
nombre0:13caracteres0
nombre1:13caracteres0
nombre2:13caracteres0
nombre3:13caracteres1
nombre4:13caracteres2
nombre5:13caracteres2
nombre6:13caracteres |
No lo he probado mucho, pero al menos funciona con el ejemplo, que consiste en varias líneas, de longitudes diferentes, e incluso hay un caso de que no comienza por los 13 caracteres dichosos (la última línea).
Actualización: He repasado tu último mensaje. Parece que los nombres tienen caracteres extraños.
La siguiente variación captura todo tipo de caracteres, usando el mismo truco de antes, de utilizar los ':default' como anclas de posición.
| Perl: | #!/usr/bin/perl
use strict;
use warnings;
use diagnostics;
while ( <DATA> ) {
while (
/ # Comienza la expresión regular
( # Capturamos ...
^ . {1, 12} # aquello que comienza la línea por menos de 13 caracteres
| # o
. {13} # aquello que tiene 13 caracteres
) # ... como $1
:default # delante de un ':default'
( # capturamos ...
.+? # un montón de caracteres
) # ... como $2
(?= # que precedan
$ # al fin de línea
| # o
. {13} :default # a otro conjunto de 13 caracteres con un ':default'
) # Esto no lo capturamos ahora, pero sí la siguiente vuelta
/iogx # Fin de la expresión regular
) {
print "$2:$1\n"; # Pintamos lo capturado
}
}
__DATA__
13caracteres0:defaultnombre013caracteres0:defaultnombre113caracteres0:defaultnombre2
13caracteres1:defaultnombre3
13caracteres2:defaultnombre413caracteres2:defaultnombre5
13caracteres:defaultnombre^^ 6 | La diferencia principal es que le decimos explícitamente que busque por el nombre más corto (.+?) antes del siguiente patrón de coincidencias. Y eliminamos /s y /m de las opciones de la expresión regular, para que '.' no encuentre los finales de línea como si fueran un carácter más. |
|

Dom Jul 27, 2008 9:53 am
|
 |
Zeokat
Perlero Frecuente

|
Registrado: 22 Ago 2006
Mensajes: 115
|
|
|
|
|
Muchiiiiisimas gracias explorer. Lo probé y funciona bien.
Otra vez más, me has salvado el pellejo
Saludos. |
|
Powered by phpBB © 2001, 2005 phpBB Group
|