¿Cómo puedo extraer las columnas de datos con Perl?
Pregunta
Tengo cadenas de este tipo
NAME1 NAME2 DEPTNAME POSITION
JONH MILLER ROBERT JIM CS ASST GENERAL MANAGER
Quiero que la salida sea nombre1 nombre2 y la posición de cómo puedo hacerlo usando split / expresiones regulares / modelo / etc y sin utilizar módulos de CPAN?
Solución
Si los datos de entrada viene como una matriz de cadenas (@strings), esto
for my $s (@strings) {
my $output = join ' ',
map /^\s*(.+)\s*$/ ? $1 : (),
unpack('A19 A15 x19 A*', $s);
print "$output\n"
}
extraería y recortar la información necesaria.
NOMBRE1 | NOMBRE2 | POSICIÓN
y
JONH MILLER | ROBERT JIM | HECHO EN GENERAL MANAGER
(La '|' se incluyeron por mí para una mejor expalnation del resultado)
Regards
RBO
Otros consejos
Se va a depender de si los campos de longitud son fijos, o si están separados pestaña. La forma más fácil (usando split) es si son pestaña separada.
my ($name1, $name2, $deptName, $position) = split("\t", $string);
Si son de longitud fija, y suponiendo que todos ellos están, por ejemplo, 10 caracteres de longitud, puede analizarlo como
my ($name1, $name2, $deptName, $position) = unpack("A10 A10 A10 A10", $string);
Suponiendo que el espacio entre los campos no están fijados de modo Separar una cadena a partir de dos o más espacios para que no se rompa el nombre como JONH MILLER en dos partes .
#!/usr/bin/perl
use strict;
use warning;
my $string = "NAME1 NAME2 DEPTNAME POSITION
JONH MILLER ROBERT JIM CS ASST GENERAL MANAGER ";
my @string_parts = split /\s\s+/, $string;
foreach my $test (@string_parts){
print"$test\n";
}
A partir de la muestra allí, un solo espacio pertenece a los datos, pero 2 o más espacios contiguos no lo hacen. De esta manera puede dividir en 2 o más espacios. La única cosa que añadir a esto es el uso de List::MoreUtils::mesh
use List::MoreUtils qw<mesh>;
my @names = map { chomp; $_ } split /\s{2,}/, <$file>;
my @records = map { chomp; { mesh( @names, @{[ split /\s{2,}/ ]} ) } } <$file>;
Considere el uso de autosplit en una sola línea de Perl desde la línea de comandos:
$ perl -F/\s{2,}/ -ane 'print qq/@F[0,1,3]\n/' file
El de una sola línea se divide en dos o más consecutivos espacios e imprimir el primer, segundo y cuarto campos, correspondientes a NAME1, NAME2 y campos de posición.
Por supuesto, esto se romperá si sólo tiene un único espacio que separa las entradas de NAME1 y NAME2, pero se necesita más información sobre el archivo con el fin de determinar cuál podría ser el mejor curso de acción.
Para dividir el espacio en blanco:
@string_parts = split /\s{2,}/, $string;
Esto dividirá $string
en una lista de subcadenas. El separador será el \s+
expresiones regulares, lo que significa uno o más espacios en blanco caracteres . Esto incluye espacios, tabulaciones, y (a menos que me equivoque) saltos de línea.
Editar veo que uno de los requisitos es que no se divida en un solo espacio, pero a dividir en dos o más. He modificado la expresión regular en consecuencia.