Rounding numbers with bash tools

Rounding numbers with bash tools

am 12.09.2007 09:23:09 von Haakon

I'm trying to clean up some textfiles that contain numbers like this:
1.2999934 2.3000124 4.199912 ..and so on.
Basically the numbers have too many digits, so I want to reduce the
amount of digits and do the appropriate rounding where necessary so
that 1.2999934 becomes 1.300.

I know awk can do something like this:
> echo 1.2999934 | awk ' { printf "%.3f\n", $0 } '
1.300

But I don't know how I can script it so that all numbers with say more
than 5 digits are found and replaced with its appropriate rounded 3-
digit equivalent.

Anyone got any tips & tricks?

Re: Rounding numbers with bash tools

am 12.09.2007 09:32:57 von Stephane CHAZELAS

2007-09-12, 00:23(-07), haakon:
> I'm trying to clean up some textfiles that contain numbers like this:
> 1.2999934 2.3000124 4.199912 ..and so on.
> Basically the numbers have too many digits, so I want to reduce the
> amount of digits and do the appropriate rounding where necessary so
> that 1.2999934 becomes 1.300.
>
> I know awk can do something like this:
>> echo 1.2999934 | awk ' { printf "%.3f\n", $0 } '
> 1.300
>
> But I don't know how I can script it so that all numbers with say more
> than 5 digits are found and replaced with its appropriate rounded 3-
> digit equivalent.
[...]

perl -pe 's/\d*\.\d{5,}/sprintf "%.3f", $&/ge'

--
Stéphane

Re: Rounding numbers with bash tools

am 12.09.2007 09:52:24 von Haakon

>
> perl -pe 's/\d*\.\d{5,}/sprintf "%.3f", $&/ge'
>
> --

That works very well :)

Re: Rounding numbers with bash tools

am 12.09.2007 10:13:05 von Haakon

> > perl -pe 's/\d*\.\d{5,}/sprintf "%.3f", $&/ge'
>
> > --
>

Is it possible to give address ranges directly to perl so that say
only the first 100 lines gets affected?

Re: Rounding numbers with bash tools

am 12.09.2007 10:33:16 von Stephane CHAZELAS

2007-09-12, 01:13(-07), haakon:
>> > perl -pe 's/\d*\.\d{5,}/sprintf "%.3f", $&/ge'
>>
>> > --
>>
>
> Is it possible to give address ranges directly to perl so that say
> only the first 100 lines gets affected?

perl -pe 's/\d*\.\d{5,}/sprintf "%.3f", $&/ge if $. <= 100'

--
Stéphane

Re: Rounding numbers with bash tools

am 12.09.2007 10:47:00 von Haakon

>
> perl -pe 's/\d*\.\d{5,}/sprintf "%.3f", $&/ge if $. <= 100'
>
> --

Exactly what I wanted! Cheers.


btw, if anyone has a python- or awk solution to it as well I'd be
interested in seeing them.

Re: Rounding numbers with bash tools

am 12.09.2007 10:47:15 von Haakon

>
> perl -pe 's/\d*\.\d{5,}/sprintf "%.3f", $&/ge if $. <= 100'
>
> --

Exactly what I wanted! Cheers.


btw, if anyone has a python- or awk solution to it as well I'd be
interested in seeing them.

Re: Rounding numbers with bash tools

am 12.09.2007 10:50:51 von Haakon

>
> perl -pe 's/\d*\.\d{5,}/sprintf "%.3f", $&/ge if $. <= 100'
>
> --

Exactly what I wanted! Cheers.


btw, if anyone has a python- or awk solution to it as well I'd be
interested in seeing them.

Re: Rounding numbers with bash tools

am 12.09.2007 12:43:36 von Stephane CHAZELAS

2007-09-12, 01:50(-07), haakon:
>>
>> perl -pe 's/\d*\.\d{5,}/sprintf "%.3f", $&/ge if $. <= 100'
>>
>
> Exactly what I wanted! Cheers.
>
>
> btw, if anyone has a python- or awk solution to it as well I'd be
> interested in seeing them.
[...]

You can do it in awk, but it's a lot more painful. You'd need to
use a combination of match(), RSTART, RLENGTH and substr() in some
loop.

I'm sure someone will come up with a ruby version soon ;),
python is not that well suited for this kind of quick text
processing job.

--
Stéphane

Re: Rounding numbers with bash tools

am 12.09.2007 20:02:47 von Cyrus Kriticos

haakon wrote:
> I'm trying to clean up some textfiles that contain numbers like this:
> 1.2999934 2.3000124 4.199912 ..and so on.
> Basically the numbers have too many digits, so I want to reduce the
> amount of digits and do the appropriate rounding where necessary so
> that 1.2999934 becomes 1.300.
>
> I know awk can do something like this:
>> echo 1.2999934 | awk ' { printf "%.3f\n", $0 } '
> 1.300

shorter:

$ x=1.2999934
$ printf "%.3f\n" $x
1.300

--
Best regards | "The only way to really learn scripting is to write
Cyrus | scripts." -- Advanced Bash-Scripting Guide

Re: Rounding numbers with bash tools

am 12.09.2007 23:12:17 von Haakon

> perl -pe 's/\d*\.\d{5,}/sprintf "%.3f", $&/ge if $. <= 100' $1

Say I want to put the above perl code into a bash-script that I call
from the commandline like this:

round_digits.sh inputfile.txt > outputfile.txt

Is it possible to do a variable substitution with the perl-code so
that the numbers of digits can be specified from the commandline when
invoking the script? Example:

round_digits.sh inputfile.txt 3 > outputfile.txt

I seem to be getting in serious quoting issues if I try something like
replacing "%3.f" with "%$2.f"

Re: Rounding numbers with bash tools

am 13.09.2007 03:51:22 von Dummy

haakon wrote:
>> perl -pe 's/\d*\.\d{5,}/sprintf "%.3f", $&/ge if $. <= 100' $1
>
> Say I want to put the above perl code into a bash-script that I call
> from the commandline like this:
>
> round_digits.sh inputfile.txt > outputfile.txt
>
> Is it possible to do a variable substitution with the perl-code so
> that the numbers of digits can be specified from the commandline when
> invoking the script? Example:
>
> round_digits.sh inputfile.txt 3 > outputfile.txt
>
> I seem to be getting in serious quoting issues if I try something like
> replacing "%3.f" with "%$2.f"


perl -spe's/\d*\.\d{5,}/sprintf "%.*f", $width || 3, $&/ge if $. <= 100' --
-width=3 inputfile.txt > outputfile.txt



John
--
Perl isn't a toolbox, but a small machine shop where you
can special-order certain sorts of tools at low cost and
in short order. -- Larry Wall

Re: Rounding numbers with bash tools

am 13.09.2007 22:39:25 von Haakon

> perl -spe's/\d*\.\d{5,}/sprintf "%.*f", $width || 3, $&/ge if $. <= 100' --
> -width=3 inputfile.txt > outputfile.txt
>
I can't make the above work. I'm new to Perl and not quite familiar
with the syntax yet. I understand that the -s switch allows for the
variable 'width' to be given after the perl program itself. Is this
the correct syntax though? The error message it gives me is:

Name "main::width" used only once: possible typo at -e line 1.
Use of uninitialized value in sprintf at -e line 1, <> line 3.
Use of uninitialized value in sprintf at -e line 1, <> line 3.
Use of uninitialized value in sprintf at -e line 1, <> line 4.
Use of uninitialized value in sprintf at -e line 1, <> line 4.
Use of uninitialized value in sprintf at -e line 1, <> line 5.
...
...
... and so on..

Re: Rounding numbers with bash tools

am 14.09.2007 01:18:54 von Dummy

haakon wrote:
>> perl -spe's/\d*\.\d{5,}/sprintf "%.*f", $width || 3, $&/ge if $. <= 100' --
>> -width=3 inputfile.txt > outputfile.txt

You do realise that that is supposed to be all on one line?


> I can't make the above work. I'm new to Perl and not quite familiar
> with the syntax yet. I understand that the -s switch allows for the
> variable 'width' to be given after the perl program itself. Is this
> the correct syntax though? The error message it gives me is:
>
> Name "main::width" used only once: possible typo at -e line 1.

The only way that you could have gotten this message is if you had used the -w
switch to perl which my example doesn't use.


> Use of uninitialized value in sprintf at -e line 1, <> line 3.
> Use of uninitialized value in sprintf at -e line 1, <> line 3.
> Use of uninitialized value in sprintf at -e line 1, <> line 4.
> Use of uninitialized value in sprintf at -e line 1, <> line 4.
> Use of uninitialized value in sprintf at -e line 1, <> line 5.

The only way that you could have gotten this message is if you had used just
$width as the second argument to sprintf() instead of my example which uses
$width || 3.



John
--
Perl isn't a toolbox, but a small machine shop where you
can special-order certain sorts of tools at low cost and
in short order. -- Larry Wall

Re: Rounding numbers with bash tools

am 14.09.2007 21:52:44 von Haakon

> perl -spe's/\d*\.\d{5,}/sprintf "%.*f", $width || 3, $&/ge if $. <= 100' --
> -width=3 inputfile.txt > outputfile.txt

Got it working, Thanks!!

Is it possible to also substitute the other values in the perl code,
specifically:
- the number of digits in the regex \d{5,}
- the number of lines to be processed.

Re: Rounding numbers with bash tools

am 14.09.2007 22:49:34 von Dummy

haakon wrote:
>> perl -spe's/\d*\.\d{5,}/sprintf "%.*f", $width || 3, $&/ge if $. <= 100' --
>> -width=3 inputfile.txt > outputfile.txt
>
> Got it working, Thanks!!
>
> Is it possible to also substitute the other values in the perl code,
> specifically:
> - the number of digits in the regex \d{5,}
> - the number of lines to be processed.


perl -spe's/\d*\.\d{$digits,}/sprintf "%.*f", $width || 3, $&/oge if $. <=
$lines' -- -width=3 -digits=5 -lines=100 inputfile.txt > outputfile.txt




John
--
Perl isn't a toolbox, but a small machine shop where you
can special-order certain sorts of tools at low cost and
in short order. -- Larry Wall