Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Format output in columns

Tags:

grep

bash

sed

awk

I was wondering how to format the following output:

-0.3116274D-04
-0.2389361D-04
-0.1192458D-04
0.3306203D-04
0.2534987D-04
0.1265136D-04
-0.2167920D-04
-0.3713258D-04
-0.2294900D-05
-0.4151710D-05
-0.7674479D-03
-0.5749288D-04
0.1393479D-04
0.6763913D-04
0.2515100D-05
-0.3638000D-06
-0.2630000D-06
-0.2445230D-06
0.1534680D-05
0.1579750D-04
0.2922010D-04
0.5390530D-04
0.8701990D-04
0.1132741D-03
0.9665700D-04
0.3337340D-04
-0.4121240D-05

into five columns, by transposing first:

-0.3116274D-04  -0.2389361D-04  -0.1192458D-04   0.3306203D-04   0.2534987D-04
 0.1265136D-04  -0.2167920D-04  -0.3713258D-04  -0.2294900D-05  -0.4151710D-05
-0.7674479D-03  -0.5749288D-04   0.1393479D-04   0.6763913D-04   0.2515100D-05
-0.3638000D-06  -0.2630000D-06  -0.2445230D-06   0.1534680D-05   0.1579750D-04
 0.2922010D-04   0.5390530D-04   0.8701990D-04   0.1132741D-03   0.9665700D-04
 0.3337340D-04  -0.4121240D-05          

My first approach was:

sed 's/\n//g' File | column -n
like image 832
Another.Chemist Avatar asked Nov 08 '13 02:11

Another.Chemist


3 Answers

The answer by traybold using printf "%14s %14s %14s %14s %14s\n" $(cat data.txt) and should probably be used, but be aware that the last line is blank padded to full width. Also, if the data file is very big (256 KiB perhaps; almost certainly before you reach 1 MiB), you will run out of space for the command line arguments to printf. The solutions below will work with files that are many megabytes in size without adversely affecting the system.

You can almost use pr in multi-column mode (pr -5 -l1 -t), but it left-justifies the columns, so the - signs won't be presented correctly. OTOH, you could then feed the output into awk to do the right-justification:

pr -5 -l1 -t File | awk '{ printf "%14s %14s %14s %14s %14s\n", $1, $2, $3, $4, $5 }'

but if you're going to drag awk into the game, it can also do the 'transposition' for you — it just takes a bit more coding to do that, though.

Your suggestion almost works, but when I tried it, I get: 0.8725220D- 0.1609633D- 0.2598447D-; the exponent of each number is gone.

Some of the wonders of pr. By default, it uses tabs to separate columns. You can override that with -s' ' or by specifying that the output width is wider (e.g. -w100). Note that argument values such as the space need to be attached to the option, at least in traditional implementations of pr (but -w 100 works OK).

$ pr -s' ' -5 -l1 -t data | awk '{printf "%14s  %14s  %14s  %14s  %14s\n", $1, $2, $3, $4, $5}'
-0.3116274D-04  -0.2389361D-04  -0.1192458D-04   0.3306203D-04   0.2534987D-04
 0.1265136D-04  -0.2167920D-04  -0.3713258D-04  -0.2294900D-05  -0.4151710D-05
-0.7674479D-03  -0.5749288D-04   0.1393479D-04   0.6763913D-04   0.2515100D-05
-0.3638000D-06  -0.2630000D-06  -0.2445230D-06   0.1534680D-05   0.1579750D-04
 0.2922010D-04   0.5390530D-04   0.8701990D-04   0.1132741D-03   0.9665700D-04
 0.3337340D-04  -0.4121240D-05                                                
$ pr -w 100 -5 -l1 -t data | awk '{printf "%14s  %14s  %14s  %14s  %14s\n", $1, $2, $3, $4, $5}'
-0.3116274D-04  -0.2389361D-04  -0.1192458D-04   0.3306203D-04   0.2534987D-04
 0.1265136D-04  -0.2167920D-04  -0.3713258D-04  -0.2294900D-05  -0.4151710D-05
-0.7674479D-03  -0.5749288D-04   0.1393479D-04   0.6763913D-04   0.2515100D-05
-0.3638000D-06  -0.2630000D-06  -0.2445230D-06   0.1534680D-05   0.1579750D-04
 0.2922010D-04   0.5390530D-04   0.8701990D-04   0.1132741D-03   0.9665700D-04
 0.3337340D-04  -0.4121240D-05  
$

All these pr | awk solutions blank-pad the last line to full width.

Here are two equivalent awk scripts that do the job in one command. One spreads the code over 2 lines, the other over 16 lines (but it is easier to read):

Option 1:

awk '{ a[i++] = $0; if (i == 5) { printf "%14s  %14s  %14s  %14s  %14s\n", a[0], a[1], a[2], a[3], a[4]; i = 0; } }
     END { if (i > 0) { printf "%14s", a[0]; for (j = 1; j < i; j++) printf "  %14s", a[j]; printf "\n"; } }' data

Option 2:

awk '{  a[i++] = $0
        if (i == 5)
        {
            printf "%14s  %14s  %14s  %14s  %14s\n", a[0], a[1], a[2], a[3], a[4]
            i = 0
        }
     }
     END {
        if (i > 0)
        {
            printf "%14s", a[0]
            for (j = 1; j < i; j++)
                printf "  %14s", a[j]
            printf "\n"
        }
     }' data

The output is the same as before except that neither of these blank-pads the last line:

-0.3116274D-04  -0.2389361D-04  -0.1192458D-04   0.3306203D-04   0.2534987D-04
 0.1265136D-04  -0.2167920D-04  -0.3713258D-04  -0.2294900D-05  -0.4151710D-05
-0.7674479D-03  -0.5749288D-04   0.1393479D-04   0.6763913D-04   0.2515100D-05
-0.3638000D-06  -0.2630000D-06  -0.2445230D-06   0.1534680D-05   0.1579750D-04
 0.2922010D-04   0.5390530D-04   0.8701990D-04   0.1132741D-03   0.9665700D-04
 0.3337340D-04  -0.4121240D-05

It would be easier and shorter to write code that did; the reset code would also do delete a to clear the array and the END block would simply test i and use the printf from the main code:

awk '{  a[i++] = $0
        if (i == 5)
        {
            printf "%14s  %14s  %14s  %14s  %14s\n", a[0], a[1], a[2], a[3], a[4]
            i = 0
            delete a
        }
     }
     END {
        if (i > 0) printf "%14s  %14s  %14s  %14s  %14s\n", a[0], a[1], a[2], a[3], a[4]
     }' data
like image 117
Jonathan Leffler Avatar answered Nov 16 '22 03:11

Jonathan Leffler


$ awk '{ORS=(NR%5?FS:RS)}1' file
-0.3116274D-04 -0.2389361D-04 -0.1192458D-04 0.3306203D-04 0.2534987D-04
0.1265136D-04 -0.2167920D-04 -0.3713258D-04 -0.2294900D-05 -0.4151710D-05
-0.7674479D-03 -0.5749288D-04 0.1393479D-04 0.6763913D-04 0.2515100D-05
-0.3638000D-06 -0.2630000D-06 -0.2445230D-06 0.1534680D-05 0.1579750D-04
0.2922010D-04 0.5390530D-04 0.8701990D-04 0.1132741D-03 0.9665700D-04
0.3337340D-04 -0.4121240D-05 $

Note that it doesn't put a newline at the end if the number of lines aren't a multiple of 5. Is that a concern?

like image 33
Ed Morton Avatar answered Nov 16 '22 03:11

Ed Morton


Try this:

printf "%14s  %14s  %14s  %14s  %14s\n" $(cat data.txt)
like image 23
traybold Avatar answered Nov 16 '22 02:11

traybold