Format output in columns

后端 未结 5 2246
慢半拍i
慢半拍i 2020-12-16 19:22

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.         


        
相关标签:
5条回答
  • 2020-12-16 19:51

    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.

    0 讨论(0)
  • 2020-12-16 19:57
    $ 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?

    0 讨论(0)
  • 2020-12-16 20:01

    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.

    0 讨论(0)
  • 2020-12-16 20:03

    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
    
    0 讨论(0)
  • 2020-12-16 20:14

    Try this:

    printf "%14s  %14s  %14s  %14s  %14s\n" $(cat data.txt)
    
    0 讨论(0)
提交回复
热议问题