Usando List::Util
(parte da biblioteca padrão desde 5.8, caso contrário, disponível no CPAN):
perl -MList::Util=max -lane 'print max(@F)'
Eu tenho um arquivo que contém vários números, como segue.
21 12 33 35 21 12 33 44 52 63 14 12 23 34 11 12 13 53 1 12 43 33 44
Como posso encontrar o máximo desses valores, que é 63
? Eu queria usar stats
, mas parece que esse comando não existe na minha máquina e não quero instalá-lo. Como posso abordar usando perl
?
Usando List::Util
(parte da biblioteca padrão desde 5.8, caso contrário, disponível no CPAN):
perl -MList::Util=max -lane 'print max(@F)'
Outras respostas são muito legais e Perl / awk é o caminho a percorrer.
Apenas por diversão, você também pode usar isso (assumindo o GNU grep
):
$ grep -Eo '[0-9]+' file | sort -rn | head -n 1
63
grep -Eo '[0-9]+' file
imprime todas as correspondências de números inteiros positivos decimais no arquivo. Cada correspondência será impressa em uma linha diferente, conforme o sinal -o
. sort -rn
ordena a lista numericamente e ao contrário, para que o primeiro número seja o maior. head -n 1
imprime a primeira linha. Por etapas:
$ grep -Eo '[0-9]+' file
21
12
33
35
21
12
33
44
52
63
14
12
23
34
11
12
13
53
1
12
43
33
44
$ grep -Eo '[0-9]+' file | sort -rn
63
53
52
44
44
43
35
34
33
33
33
23
21
21
14
13
12
12
12
12
12
11
1
Estou ciente de que isso não é perl:
awk '{for(i=1;i<=NF;i++) if($i>maxval) maxval=$i;}; END { print maxval;}' file
Outra solução perl
:
$ perl -MList::Util=max -anle 'print max(@F)' file
63
Isso funcionará com o arquivo contendo uma linha, se você tiver várias linhas no arquivo e quiser encontrar o valor máximo em todas as linhas, tente:
$ perl -MList::Util=max -alne '$tmp = max @F; $max = $tmp if $max < $tmp; END { print $max }'
Isso funciona no Ubuntu, mas não no MacOS:
echo "21 12 33 35 21 12 33 44 52 63 14 12 23 34 11 12 13 53 1 12 43 33 44" | grep -oE "[0-9]*" | sort -nr | head -n 1
Primeiro, grep para os padrões que correspondem a um número (add., se você tiver decimais), então, classifique numérico na ordem inversa e, em seguida, escolha o primeiro resultado.
Aqui está uma abordagem Perl mais rápida que não requer classificação:
$ echo '21 12 33 35 21 12 33 44 52 63 14 12 23 34 11 12 13 53 1 12 43 33 44' |
perl -lane 'map{$m=$_ if $_>$m}@F; print $m'
ou, como sugerido por @Gnouc nos comentários:
$ echo '21 12 33 35 21 12 33 44 52 63 14 12 23 34 11 12 13 53 1 12 43 33 44' |
perl -lane '$m<$_ and $m=$_ for @F; print $m'
Se você quisesse suportar diferentes tipos de números (-2, 1E-20, inf, 0x2f, 0b0101, 0777 ...), e não apenas números inteiros decimais positivos, você poderia fazer:
perl -lne '
while (m{(?!<\w)(?:(0x[0-9a-f]+|
0b[01]+|
0[0-7]+)|
[-+]?(\d+(\.\d*)?|\.\d+)(e[-+]?\d+)?|
infinity|inf)(?!\w)}xgi) {
$v = defined($1) ? oct($1) : $&;
$m = $& unless defined($m) && $m >= $v
}
END {print $m if defined $m}'
Não há necessidade de awk, grep ou perl.
{
for n in 21 12 33 35 21 12 33 44 52 63 14 12 23 34 11 12 13 53 1 12 43 33 44
do
echo $n
done
} | sort | tail -n1
Sim, isso não é perl
, mas eu gosto do GNU awk
para isso
awk -v RS='[[:space:]]+' 'BEGIN{max=-inf};{max = $0>max? $0: max};END{print max}' file
63
grep '[0-9]*' number.sh | sort -rn | head -1
Tags text-processing perl