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.
Wow, haven't seen this in a while. There are several ways:
The ol' pr command was used for this type of work -- especially if you wanted those columns going vertically instead of horizontally.
However, I would use printf
which allows me to keep the text a constant width, and then use a counter and the modulo operator to count when I have five items in a line. The modulo operator is sometimes called a remainder operator. However, it functions like a clock:
#!/bin/bash
#
count=0
while read number
do
((count+=1))
printf "%14.14s " $number
if ((count % 5 == 0))
then
printf "\n"
fi
done < $file
printf "\n"
The format for the printf
is missing the minus ( i.e. %-14.14s
) which forces the text to be aligned to the right instead of the left. That way the minus doesn't throw me off.
$ 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?
A little bit tricky alternative:
columnPrint(){
select foo in $(cat); do break; done; <<!SELECTEOF
1
!SELECTEOF
};
cat data.txt | columnPrint;
# or simply columnPrint < data.txt
Compared with @traybold approach, it has the drawback that items are numbered (which could not be what you want), but it also has the advantage of automatically adapting the number of columns to the input strings and terminal width.
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
Try this:
printf "%14s %14s %14s %14s %14s\n" $(cat data.txt)