How can I align the columns of tables in Bash?

前端 未结 9 1977
一个人的身影
一个人的身影 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:56

    Use column command:

    column -t -s' ' filename
    
    0 讨论(0)
  • 2020-12-02 09:02
    function printTable()
    {
        local -r delimiter="${1}"
        local -r data="$(removeEmptyLines "${2}")"
    
        if [[ "${delimiter}" != '' && "$(isEmptyString "${data}")" = 'false' ]]
        then
            local -r numberOfLines="$(wc -l <<< "${data}")"
    
            if [[ "${numberOfLines}" -gt '0' ]]
            then
                local table=''
                local i=1
    
                for ((i = 1; i <= "${numberOfLines}"; i = i + 1))
                do
                    local line=''
                    line="$(sed "${i}q;d" <<< "${data}")"
    
                    local numberOfColumns='0'
                    numberOfColumns="$(awk -F "${delimiter}" '{print NF}' <<< "${line}")"
    
                    # Add Line Delimiter
    
                    if [[ "${i}" -eq '1' ]]
                    then
                        table="${table}$(printf '%s#+' "$(repeatString '#+' "${numberOfColumns}")")"
                    fi
    
                    # Add Header Or Body
    
                    table="${table}\n"
    
                    local j=1
    
                    for ((j = 1; j <= "${numberOfColumns}"; j = j + 1))
                    do
                        table="${table}$(printf '#| %s' "$(cut -d "${delimiter}" -f "${j}" <<< "${line}")")"
                    done
    
                    table="${table}#|\n"
    
                    # Add Line Delimiter
    
                    if [[ "${i}" -eq '1' ]] || [[ "${numberOfLines}" -gt '1' && "${i}" -eq "${numberOfLines}" ]]
                    then
                        table="${table}$(printf '%s#+' "$(repeatString '#+' "${numberOfColumns}")")"
                    fi
                done
    
                if [[ "$(isEmptyString "${table}")" = 'false' ]]
                then
                    echo -e "${table}" | column -s '#' -t | awk '/^\+/{gsub(" ", "-", $0)}1'
                fi
            fi
        fi
    }
    
    function removeEmptyLines()
    {
        local -r content="${1}"
    
        echo -e "${content}" | sed '/^\s*$/d'
    }
    
    function repeatString()
    {
        local -r string="${1}"
        local -r numberToRepeat="${2}"
    
        if [[ "${string}" != '' && "${numberToRepeat}" =~ ^[1-9][0-9]*$ ]]
        then
            local -r result="$(printf "%${numberToRepeat}s")"
            echo -e "${result// /${string}}"
        fi
    }
    
    function isEmptyString()
    {
        local -r string="${1}"
    
        if [[ "$(trimString "${string}")" = '' ]]
        then
            echo 'true' && return 0
        fi
    
        echo 'false' && return 1
    }
    
    function trimString()
    {
        local -r string="${1}"
    
        sed 's,^[[:blank:]]*,,' <<< "${string}" | sed 's,[[:blank:]]*$,,'
    }
    

    SAMPLE RUNS

    $ cat data-1.txt
    HEADER 1,HEADER 2,HEADER 3
    
    $ printTable ',' "$(cat data-1.txt)"
    +-----------+-----------+-----------+
    | HEADER 1  | HEADER 2  | HEADER 3  |
    +-----------+-----------+-----------+
    
    $ cat data-2.txt
    HEADER 1,HEADER 2,HEADER 3
    data 1,data 2,data 3
    
    $ printTable ',' "$(cat data-2.txt)"
    +-----------+-----------+-----------+
    | HEADER 1  | HEADER 2  | HEADER 3  |
    +-----------+-----------+-----------+
    | data 1    | data 2    | data 3    |
    +-----------+-----------+-----------+
    
    $ cat data-3.txt
    HEADER 1,HEADER 2,HEADER 3
    data 1,data 2,data 3
    data 4,data 5,data 6
    
    $ printTable ',' "$(cat data-3.txt)"
    +-----------+-----------+-----------+
    | HEADER 1  | HEADER 2  | HEADER 3  |
    +-----------+-----------+-----------+
    | data 1    | data 2    | data 3    |
    | data 4    | data 5    | data 6    |
    +-----------+-----------+-----------+
    
    $ cat data-4.txt
    HEADER
    data
    
    $ printTable ',' "$(cat data-4.txt)"
    +---------+
    | HEADER  |
    +---------+
    | data    |
    +---------+
    
    $ cat data-5.txt
    HEADER
    
    data 1
    
    data 2
    
    $ printTable ',' "$(cat data-5.txt)"
    +---------+
    | HEADER  |
    +---------+
    | data 1  |
    | data 2  |
    +---------+
    

    REF LIB at: https://github.com/gdbtek/linux-cookbooks/blob/master/libraries/util.bash

    0 讨论(0)
  • 2020-12-02 09:05

    Not sure where you were running this, but the code you posted would not produce the output you gave, at least not in the bash that I'm familiar with.

    Try this instead:

    stringarray=('test' 'some thing' 'very long long long string' 'blah')
    numberarray=(1 22 7777 8888888888)
    anotherfieldarray=('other' 'mixed' 456 'data')
    array_size=4
    
    for((i=0;i<array_size;i++))
    do
        echo ${stringarray[$i]} $'\x1d' ${numberarray[$i]} $'\x1d' ${anotherfieldarray[$i]}
    done | column -t -s$'\x1d'
    

    Note that I'm using the group seperator character (1d) intead of tab, because if you are getting these arrays from a file, they might contain tabs.

    0 讨论(0)
提交回复
热议问题