perl tem um módulo chamado Scalar::Util
(incluído no perl desde v5.8) que tem uma função útil chamada looks_like_number()
, que pode ser usada para detectar se um campo é um número ou não.
looks_like_number
não é perfeito, mas é muito bom.
O esboço simples de um programa perl simples para fazer o que você quer pode ser algo como isto:
#! /usr/bin/perl
use Scalar::Util qw(looks_like_number);
while(<>) {
chomp;
my @fields=split("\t");
foreach my $f (0..scalar @fields-1) {
if (looks_like_number($fields[$f])) {
$fields[$f] += 42;
$fields[$f] *= 7;
$fields[$f] = sprintf("%.2f",$fields[$f]);
}
}
print join("\t",@fields),"\n";
}
Se você receber dados de amostra acima como entrada, imprime isto:
file name size owner
file1.txt 380.41 root
file2.txt 295.21 user1
file3.txt 2016.00 user2
file4.txt 86709.00 root
file5.txt 441.00 user3
file6.txt 2016.00 user1
file name owner last modified last accessed
text4.txt root 383.11 388.71
text5.txt user3 401.33 532.00
file1.txt root 455.00 511.02
Aqui está outra versão do script que usa o Math :: BigFloat para todos os cálculos, arredondando decimais para 2 dígitos.
#! /usr/bin/perl
use Scalar::Util qw(looks_like_number);
use Math::BigFloat;
while(<>) {
chomp;
my @fields=split("\t");
foreach my $f (0..scalar @fields-1) {
if (looks_like_number($fields[$f])) {
my $BF = Math::BigFloat->new($fields[$f]);
$BF->badd(42);
$BF->bmul(7);
$BF->ffround(-2);
$fields[$f] = $BF->bstr();
}
}
print join("\t",@fields),"\n";
}
exemplo de entrada:
file name owner last modified last accessed
text4.txt root 12.73 13.53
text5.txt user3 15.3333 34
file6.txt root 903709792518875002.42857142857142857142 903709792518875002
file7.txt root 6659166111488656281486807152009765625 539422123247359763587428687890625
saída:
file name owner last modified last accessed
text4.txt root 383.11 388.71
text5.txt user3 401.33 532.00
file6.txt root 6325968547632125311.00 6325968547632125308.00
file7.txt root 46614162780420593970407650064068359669.00 3775954862731518345112000815234669.00