2012-10-07 15 views
28

Me gustaría dar salida a un texto con formato de tabla. Lo que traté de hacer fue repetir los elementos de una matriz con '\ t', pero estaba desalineada. mi códigoBash Output Tables

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

Mi salida

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

salida deseada

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

Respuesta

39

printf es un poco sorprendente programa que mucha gente se olvida existe. Es bastante poderoso.

$ 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 

Aviso que utiliza %10s para cuerdas. %s es la parte importante. Le dice que use una cadena. El 10 en el medio dice cuántas columnas debe ser. %d es para números (dígitos).

man 1 printf para obtener más información.

+14

solo un consejo que es útil al imprimir tablas: '% -10s' generará series de longitud izquierda 10 alineadas a la izquierda – steffen

74

Uso de comandos columna:

column -t -s' ' filename 
+0

'printf' también puede ser útil. – Mat

+2

No se ajusta a sus necesidades así. –

+0

@sputnick Esto se ajusta exactamente a sus necesidades. La razón por la que hace el '\ t', que es innecesario, es hacer una columna tabular que le da un espacio de longitud fija entre las palabras. Todo lo que tiene que hacer es canalizar la salida a 'columna'. –

5

para tener la misma salida exacta como sea necesario, se necesita formatear el archivo así:

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

Y luego usando:

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

¿Qué está haciendo el' $ 'en' $ '\ t''? – rjmunro

+0

Es una pestaña en la sintaxis de bash, consulte http://mywiki.wooledge.org/Quotes –

+0

El uso de pestañas se vuelve completamente inutilizable si 2 columnas tienen más de 5 caracteres de tamaño diferente. – UtahJarhead

3

No estoy seguro de dónde estaba ejecutando esto, pero el código que publicó no produciría el resultado que dio, al menos no en el bash con el que estoy familiarizado.

Tal vez puedas probar:

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' 

Tenga en cuenta que estoy usando el carácter separador de grupo (1d) intead de pestaña, porque si usted está recibiendo estas matrices a partir de un archivo, que pueden contener fichas.

1

Es más fácil de lo que piensas.

Si está trabajando con un separados por archivo de punto y coma y cabecera también:

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

Si está trabajando con array (pestaña como separador utilizando):

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

ejecuta el ejemplo

$ 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 en: https://github.com/gdbtek/linux-cookbooks/blob/master/libraries/util.bash