Comment aligner les colonnes des tableaux dans Bash?

j'aimerais sortir un texte de format de tableau. Ce que j'ai essayé de faire était l'écho des éléments d'un tableau avec 't' mais il a été mal aligné. mon code

for((i=0;i<array_size;i++));
do
   echo stringarray[$i] $'t' numberarray[$i] $'t' anotherfieldarray[$i]
done;

Ma sortie

a very long string..........     112232432      anotherfield
a smaller string         123124343     anotherfield

sortie désirée

a very long string..........     112232432      anotherfield
a smaller string                 123124343      anotherfield
36

7 réponses

printf est un petit programme étonnant que beaucoup de gens oublient existe. C'est plutôt puissant.

$ 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

Notez que j'ai utilisé %10s pour les chaînes. %s est la partie importante. Il lui dit d'utiliser une chaîne de caractères. Le 10 au milieu dit combien de colonnes il doit être. %d pour les chiffres (chiffres).

man 1 printf pour plus d'information.

49
répondu UtahJarhead 2013-05-08 09:28:52

utiliser la commande de colonne:

column -t -s' ' filename
84
répondu P.P. 2012-10-07 12:39:10

pour avoir la même sortie exacte que vous avez besoin, vous devez formater le fichier comme cela:

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

et ensuite en utilisant:

$ column -t -s $'\t' FILE
a very long string..........  112232432  anotherfield
a smaller string              123124343  anotherfield
8
répondu Gilles Quenot 2012-10-07 13:07:25

Je ne sais pas où vous avez lancé ceci, mais le code que vous avez posté ne produirait pas la sortie que vous avez donnée, du moins pas dans la bash que je connais.

essayez plutôt ceci:

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'

notez que j'utilise le caractère de séparation de groupe (1D) au lieu de tab, parce que si vous obtenez ces tableaux à partir d'un fichier, ils peuvent contenir des tabs.

3
répondu Benubird 2015-03-06 09:59:21
function printTable()
{
    local -r delimiter=""
    local -r data="$(removeEmptyLines "")"

    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(" ", "-", "151900920")}1'
            fi
        fi
    fi
}

function removeEmptyLines()
{
    local -r content=""

    echo -e "${content}" | sed '/^\s*$/d'
}

function repeatString()
{
    local -r string=""
    local -r numberToRepeat=""

    if [[ "${string}" != '' && "${numberToRepeat}" =~ ^[1-9][0-9]*$ ]]
    then
        local -r result="$(printf "%${numberToRepeat}s")"
        echo -e "${result// /${string}}"
    fi
}

function isEmptyString()
{
    local -r string=""

    if [[ "$(trimString "${string}")" = '' ]]
    then
        echo 'true' && return 0
    fi

    echo 'false' && return 1
}

function trimString()
{
    local -r string=""

    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  |
+---------+

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

2
répondu Nam Nguyen 2018-03-08 18:50:32

c'est plus facile que vous ne le pensez.

si vous travaillez avec un fichier séparé par un point-virgule et en-tête aussi:

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

si vous travaillez avec array (en utilisant tab comme séparateur):

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
1
répondu Renan Benedicto Pereira 2017-01-26 17:17:21

awk solution qui traite de stdin

puisque column n'est pas positif, peut-être que c'est:

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 [ "$file" = - ]; then
    rm "$file"
  fi
)

Test:

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

les commandes de Test:

mycolumn file
mycolumn <file
mycolumn - <file

sortie pour tous:

      12   1234      1
12345678      1    123
    1234 123456 123456

voir aussi:

0