5

There is a file I have which look

555.92 569.472 582.389 648.078 999.702 1040.75 1386.24 1418.47 1998.26 2182.13 2384.3

I would need to round every number like this

556 569 582 

Ideally i don't need to create a tmp file. How to do that ?

1
  • The answers provided are good (and better than what I'm just about to mention), but just for the fun of mentionning it: a possibility is to add "0.5" to each number and keep just the integer part (for ex: drop the decimal part). There are many ways to do that one (and many caveats, especially when you reach the maximum value, which in turns depends on the program and its implementation) Jun 24, 2015 at 9:51

7 Answers 7

10

Run the contents of the file through printf function.

 $ xargs -a numbers.txt -n1 printf "%1.f "                                   
    556 569 582 648 1000 1041 1386 1418 1998 2182 2384 

Also ,Ubuntu has nice little program called numfmt which allows formating numbers to user defined standards, and human readable.

For example,

$ xargs -a numbers.txt -n1 numfmt  --to=si --round=up | xargs echo 
556 570 583 649 1.0K 1.1K 1.4K 1.5K 2.0K 2.2K 2.4K

Check man numfmt for more info.

1
  • or even printf "%1.f " $(cat numbers.txt) Jun 24, 2015 at 6:21
5

bash can only handle integer arithmetic. Use a more powerful language, e.g. Perl:

perl -ane 'printf "%.0f ", $_ for @F' file
  • -n reads the input line by line
  • -a splits each line on whitespace to the @F array
  • %.0f is a flow format with zero digits after the decimal point
5

Another python solution (one -liner). Run in a terminal:

python3 -c "[print(round(float(n))) for n in open('f').read().split()]"

Where 'f' is the source file with your floats, between single quotes, e.g.:

python3 -c "[print(round(float(n))) for n in open('/home/jacob/Bureaublad/test').read().split()]"

Output:

556
569
582
648
1000
1041
1386
1418
1998
2182
2384

Another way of output

If you'd like the figures in one row:

python3 -c "[print(round(float(n)), end=' ') for n in open('f').read().split()]"

(Thanks @Oli!)

Output:

556 569 582 648 1000 1041 1386 1418 1998 2182 2384

Explanation

The command:

python3 -c "[print(round(float(n))) for n in open('f').read().split()]"

in sections:

open('f').read().split()

reads the file 'f', splits it into floats (now still as string)

round(float(n))

First interprets the string n as float, rounds it to an integer

[print(round(float(n))) for n in open('f').read().split()]

finally, generates the print command, to print all rounded floats.

7
  • @HenkLangeveld Thanks a lot for the edit, but I'd like to keep the "one liner" :) Jun 23, 2015 at 14:15
  • I'll hold off editing, but you can use Py3k's print(..., end=' ') argument instead of needing to do a separate ' '.join(...). It would read something like: for n in open('f').read().split(): print(int(round(float(n))), end=' '). Shorter and because you skip list comprehension, it's somewhat easier to follow for Python novices too.
    – Oli
    Jun 23, 2015 at 22:10
  • @Oli much shorter, and much nicer to look at :). Thanks! Jun 24, 2015 at 6:14
  • @Oli I am not sure..is it a good idea to take the whole file in memory even if it is of much bigger size?
    – heemayl
    Jun 24, 2015 at 7:19
  • @heemayl not sure how big a file you are imagining, but on a file, more than a million floats, (written to a file, since printing in the terminal is what takes the time, not processing the floats) it is done in a split second. Also, looking at the question, there is only one line, so reading line by line is actually equal to loading the whole file :) Jun 24, 2015 at 7:32
4

Where is the awk version? printf can also be used in awk:

awk '{for(i=1;i<=NF;i++) {printf "%0.f ",$i} printf "\n"}'

or inplace without a temporary file (Thx @muru)

awk -i inplace '{for(i=1;i<=NF;i++) {printf "%0.f ",$i} printf "\n"}'

Example

% cat foo
555.92 569.472 582.389 648.078 999.702 1040.75 1386.24 1418.47 1998.26 2182.13 2384.3

% awk '{
  for(i=1;i<=NF;i++) {
    printf "%0.f ",$i
  }
  printf "%s","\n"
}' foo
556 569 582 648 1000 1041 1386 1418 1998 2182 2384
1
  • With -i inplace for in-place editing, thus avoiding a temporary file like OP wants.
    – muru
    Jun 23, 2015 at 14:17
4

Using python:

#!/usr/bin/env python2
with open('/path/to/file.txt') as f:
    for line in f:
        numbers = line.strip().split(' ')
        for num in numbers:
            print int(round(float(num))),
  • The list numbers will contain all the numbers spitted on spaces (line.rstrip().split(' '))

  • Then we have used the round() function to round the floating point numbers

  • As the inputs are stored as srings we need to use the float() function to convert them to floats

  • The int() function will print the number discarding the decimal points i.e. only the integer portion

Output :

556 569 582 648 1000 1041 1386 1418 1998 2182 2384
0
2

Using perl:

perl -ne 'printf("%.0f ", $_) for split' file
2

This should work for you:

perl -ne '@l=split(/\s+/,$_); foreach(@l){printf("%.0f",$_); print " "}'

you can use it like

echo "555.92 569.472 582.389" | perl -ne '
  @l=split(/\s+/,$_);
  foreach(@l) {
    printf("%.0f",$_);
    print " "
  }'
1
  • Try this: perl -F'/\s/' -ane 'foreach(@F){printf "%.0f ",$_}' foo
    – A.B.
    Jun 23, 2015 at 17:24

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .