Se o uso de memória não for realmente um problema, uma versão de uma passagem no perl provavelmente seria:
perl -ane 'END { $"=""; print "@res"; } if($F[4] =~ /^\d+/ and $F[4] > $max) {
$max = $F[4]; @res = (); } push @res, $_ if($F[4] =~ /^\d+$/ and $max == $F[4]);' infile
-n
diz ao perl para processar a linha infile
one por vez passando cada linha para os comandos especificados em -e
. O -a
diz ao perl para expandir cada linha ao redor do separador de campos (o padrão é espaço) e atribui isso a uma matriz chamada @F
. O resultado é para cada linha que podemos processá-lo e usar $F[n]
para se referir ao enésimo elemento dessa linha.
O próprio perl:
END { $"=""; print "@res"; } # at the end of execution set the field separator to
# empty and print the contents of @res, which includes
# newlines when the matching rows were stored
if($F[4] =~ /^\d+/ and $F[4] > $max) { # if the 5th element of the line is solely a
$max = $F[4]; @res = (); # number and it's greater than $max (which
} # starts as undefined), set $max to this number
# and empty the @res results array.
push @res, $_ # push this line to @res ...
if($F[4] =~ /^\d+$/ and $max == $F[4]); # IF the 5th element is solely a
# number and equal to $max
A lógica é que $max
é iniciado como indefinido e a @res
está vazia. Na primeira vez que encontramos um número na coluna 5, armazenamos isso em $max
e vazio @res
. Isso também tem o efeito colateral de esvaziar @res
se encontrarmos um novo valor máximo na coluna 5 nas linhas a seguir. Como uma verificação separada, se a coluna 5 for igual a $max
, adicione essa linha a @res
(armazene linhas com o valor máximo atual). Repita para todas as linhas e, em seguida, o bloco END { }
é executado, imprimindo o conteúdo do array @res
results sem o separador de espaço de espaço principal normalmente definido em $"
.
Isso provavelmente também pode ser alcançado em awk
, mas meu awk-fu
não é tão bom assim!