How can I align the columns of tables in Bash?

前端 未结 9 1976
一个人的身影
一个人的身影 2020-12-02 08:25

I\'d like to output a table format text. What I tried to do was echo the elements of an array with \'\\t\', but it was misaligned.

My code

for((i=0;i         


        
相关标签:
9条回答
  • 2020-12-02 08:40

    printf is great, but people forget about it.

    $ for num in 1 10 100 1000 10000 100000 1000000; do printf "%10s %s\n" $num "foobar"; done
             1 foobar
            10 foobar
           100 foobar
          1000 foobar
         10000 foobar
        100000 foobar
       1000000 foobar
    
    $ for((i=0;i<array_size;i++));
    do
        printf "%10s %10d %10s" stringarray[$i] numberarray[$i] anotherfieldarray[%i]
    done
    

    Notice I used %10s for strings. %s is the important part. It tells it to use a string. The 10 in the middle says how many columns it is to be. %d is for numerics (digits).

    man 1 printf for more info.

    0 讨论(0)
  • 2020-12-02 08:41

    Below code has been tested and does exactly what is requested in the original question.

    Parameters: %30s Column of 30 char and text right align. %10d integer notation, %10s will also work. Added clarification included on code comments.

    stringarray[0]="a very long string.........."
    # 28Char (max length for this column)
    numberarray[0]=1122324333
    # 10digits (max length for this column)
    anotherfield[0]="anotherfield"
    # 12Char (max length for this column)
    stringarray[1]="a smaller string....."
    numberarray[1]=123124343
    anotherfield[1]="anotherfield"
    
    printf "%30s %10d %13s" "${stringarray[0]}" ${numberarray[0]} "${anotherfield[0]}"
    printf "\n"
    printf "%30s %10d %13s" "${stringarray[1]}" ${numberarray[1]} "${anotherfield[1]}"
    # a var string with spaces has to be quoted
    printf "\n Next line will fail \n"      
    printf "%30s %10d %13s" ${stringarray[0]} ${numberarray[0]} "${anotherfield[0]}"
    
    
    
      a very long string.......... 1122324333  anotherfield
             a smaller string.....  123124343  anotherfield
    
    0 讨论(0)
  • 2020-12-02 08:45

    awk solution that deals with stdin

    Since column is not POSIX, maybe this is:

    mycolumn() (
      file="${1:--}"
      if [ "$file" = - ]; then
        file="$(mktemp)"
        cat > "${file}"
      fi
      awk '
      FNR == 1 { if (NR == FNR) next }
      NR == FNR {
        for (i = 1; i <= NF; i++) {
          l = length($i)
          if (w[i] < l)
            w[i] = l
        }
        next
      }
      {
        for (i = 1; i <= NF; i++)
          printf "%*s", w[i] + (i > 1 ? 1 : 0), $i
        print ""
      }
      ' "$file" "$file"
      if [ "$1" = - ]; then
        rm "$file"
      fi
    )
    

    Test:

    printf '12 1234 1
    12345678 1 123
    1234 123456 123456
    ' > file
    

    Test commands:

    mycolumn file
    mycolumn <file
    mycolumn - <file
    

    Output for all:

          12   1234      1
    12345678      1    123
        1234 123456 123456
    

    See also:

    • Using awk to align columns in text file?
    • AWK: go through the file twice, doing different tasks
    0 讨论(0)
  • 2020-12-02 08:50

    Just in case someone wants to do that in PHP I posted a gist on Github

    https://gist.github.com/redestructa/2a7691e7f3ae69ec5161220c99e2d1b3

    simply call:

    $output = $tablePrinter->printLinesIntoArray($items, ['title', 'chilProp2']);
    

    you may need to adapt the code if you are using a php version older than 7.2

    after that call echo or writeLine depending on your environment.

    0 讨论(0)
  • 2020-12-02 08:51

    It's easier than you wonder.

    If you are working with a separated by semicolon file and header too:

    $ (head -n1 file.csv && sort file.csv | grep -v <header>) | column -s";" -t
    

    If you are working with array (using tab as separator):

    for((i=0;i<array_size;i++));
    do
    
       echo stringarray[$i] $'\t' numberarray[$i] $'\t' anotherfieldarray[$i] >> tmp_file.csv
    
    done;
    
    cat file.csv | column -t
    
    0 讨论(0)
  • 2020-12-02 08:54

    To have the exact same output as you need, you need to format the file like that :

    a very long string..........\t     112232432\t     anotherfield\n
    a smaller string\t      123124343\t     anotherfield\n
    

    And then using :

    $ column -t -s $'\t' FILE
    a very long string..........  112232432  anotherfield
    a smaller string              123124343  anotherfield
    
    0 讨论(0)
提交回复
热议问题