How can I align the columns of tables in Bash?
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.
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.txtHEADER 1,HEADER 2,HEADER 3$ printTable ',' "$(cat data-1.txt)"+-----------+-----------+-----------+| HEADER 1 | HEADER 2 | HEADER 3 |+-----------+-----------+-----------+$ cat data-2.txtHEADER 1,HEADER 2,HEADER 3data 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.txtHEADER 1,HEADER 2,HEADER 3data 1,data 2,data 3data 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.txtHEADERdata$ printTable ',' "$(cat data-4.txt)"+---------+| HEADER |+---------+| data |+---------+$ cat data-5.txtHEADERdata 1data 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