Eu estaria pensando em "usar perl":
#!/usr/bin/env perl
use strict;
use warnings;
use Time::Piece;
#get the column names out of the file. We remove the trailing linefeed.
#<> is the magic input file handle, so it reads from STDIN or files
#specified on command line, e.g. myscript.pl file_to_process.csv
my @headers = split ( /,/, <> =~ s/\n//r );
while ( <> ) {
chomp; #strip linefeed.
my %stuff;
#this makes use of the fact we know the headers already
#so we can map from the line into named columns.
@stuff{@headers} = split /,/; #read comma sep into hash
#DOB:
#take date, parse it into a unix time, then use strftime to output "Mon year"
print Time::Piece -> strptime ( $stuff{'DOB'}, "%d/%m/%Y" ) -> strftime("%b %Y");
#regex match against AnimalNumber, and then join it with space separation.
print "\t"; #separator
print join ( " ", $stuff{'AnimalNumber'} =~ m/(\d+)(\d)(\d{4})/ );
print "\n";
}
Esta saída:
Feb 2010 1612892 4 0602
Jan 2009 1414244 9 0333
Jan 2007 1514244 2 0395
Isso funciona por:
- Lendo
<>
, que é o identificador de arquivo mágico - recebe informações de pipes ou nomes de arquivos.
- Lemos a primeira linha e transformamos isso em uma matriz de
@headers
.
- nós iteramos cada linha adicional e mapeamos os valores separados por vírgulas em um hash (chamado
%stuff
).
- Extraia
DOB
de %stuff
- e processe-o usando strptime/strftime
em uma data, conforme necessário.
- extraia
AnimalNumber
de %stuff
e use um padrão regex para extrair os números que você procura depois
- porque usamos vários grupos de captura, os elementos capturados são retornados como uma lista, que podemos ficar juntos (com um delimitador de espaço) usando
join
.
Edit: Porque você está olhando para a classificação - você terá que ler todo o lote primeiro na memória (o que acima não é por motivos de eficiência).
No entanto:
#!/usr/bin/env perl
use strict;
use warnings;
use Data::Dumper;
use Time::Piece;
my @headers = split( /,/, <> =~ s/\n//r );
my @records;
while (<>) {
chomp; #strip linefeed.
my %stuff;
#this makes use of the fact we know the headers already
#so we can map from the line into named columns.
@stuff{@headers} = split /,/; #read comma sep into hash
#DOB:
#take date, parse it into a unix time, then use strftime to output "Mon year"
$stuff{'formtime'} =
Time::Piece->strptime( $stuff{'DOB'}, "%d/%m/%Y" )->strftime("%b %Y");
#regex match against AnimalNumber, and then join it with space separation.
#separator
$stuff{'number_arr'} = [ $stuff{'AnimalNumber'} =~ m/(\d+)(\d)(\d{4})/ ];
push( @records, \%stuff );
}
foreach
my $record ( sort { $b->{'number_arr'}->[2] <=> $a->{'number_arr'}->[2] }
@records )
{
print join( "\t",
$record->{'formtime'}, join( " ", @{ $record->{'number_arr'} } ),
),
"\n";
}
Semelhante ao anterior, mas pré-processamos cada registro em uma matriz de hashes e usamos sort
da saída antes da impressão - com base no campo "chave" - último grupo de 4 dígitos em number_arr
.