2012-10-07 21 views
28

Vorrei produrre un testo in formato tabella. Quello che ho cercato di fare era echo gli elementi di un array con '\ t' ma era disallineato. mio codiceTabelle di output Bash

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

La mia uscita

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

output desiderato

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

risposta

39

printf è un piccolo programma sorprendente che molte persone dimenticano esiste. È piuttosto potente.

$ 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 

Avviso Ho usato %10s per le stringhe. %s è la parte importante. Gli dice di usare una corda. Lo 10 nel mezzo indica quante colonne deve essere. %d è per numeri (cifre).

man 1 printf per ulteriori informazioni.

+14

solo un consiglio utile quando si stampano le tabelle: '% -10s' genera stringhe allineate a sinistra di lunghezza 10 – steffen

74

Utilizzare il comando colonna:

column -t -s' ' filename 
+0

'printf' può anche essere utile. – Mat

+2

Non soddisfa i suoi bisogni in questo modo. –

+0

@sputnick Questo corrisponde esattamente alle sue esigenze. La ragione per cui fa il '\ t', che non è necessario, è di fare da solo una colonna tabulare che dà uno spazio di lunghezza fissa tra le parole. Tutto quello che deve fare è canalizzare l'output su 'column'. –

5

di avere la stessa uscita esatta di cui hai bisogno, è bisogno di formattare il file così:

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

E quindi utilizzando:

$ column -t -s $'\t' FILE 
a very long string.......... 112232432 anotherfield 
a smaller string    123124343 anotherfield 
+0

Cosa sta facendo' $' in '$ '\ t''? – rjmunro

+0

È una scheda nella sintassi di bash, vedi http://mywiki.wooledge.org/Quotes –

+0

L'uso delle tabstop diventa completamente inutilizzabile se 2 colonne hanno più di circa 5 caratteri di dimensioni diverse. – UtahJarhead

3

Non sai dove stavi girando, ma il codice che hai postato non avrebbe prodotto l'output che hai dato, almeno non nella bash che mi è familiare.

Prova a modificare:

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' 

Nota che sto usando il carattere separatore di gruppo (1d) intead della scheda, perché se si stanno ottenendo questi array da un file, potrebbero contenere schede.

1

È più facile di quello che ti chiedi.

Se si lavora con un separati da file di virgola e intestazione troppo:

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

Se si lavora con array (tab come separatore utilizzando):

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
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:]]*$,,' 
} 

RUNS CAMPIONE

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

RE F LIB a: https://github.com/gdbtek/linux-cookbooks/blob/master/libraries/util.bash