texto - ¿Cómo alinear las columnas de tablas en Bash?
recorrer string bash (7)
Me gustaría dar salida a un texto de formato de tabla. Lo que traté de hacer fue repetir los elementos de una matriz con ''/ t'', pero estaba desalineada. mi código
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
Es más fácil de lo que te preguntas.
Si está trabajando con un archivo y un encabezado separados por punto y coma también:
$ (head -n1 file.csv && sort file.csv | grep -v <header>) | column -s";" -t
Si está trabajando con una matriz (usando la pestaña como separador):
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
No estoy seguro de dónde estaba ejecutando esto, pero el código que publicaste no produciría el resultado que me diste, al menos no en el bash con el que estoy familiarizado.
Pruebe esto en su lugar:
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 de separador de grupo (1d) intead de pestaña, porque si obtiene estas matrices de un archivo, pueden contener pestañas.
Para tener exactamente el mismo resultado que necesita, debe formatear el archivo de esa manera:
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
Use el comando de columna:
column -t -s'' '' filename
printf
es un pequeño programa sorprendente que mucha gente olvida que 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
Observe que usé %10s
para cadenas. %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 más información.
awk
solución que se ocupa de stdin
Como la column
no es POSIX, tal vez esto sea:
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
)
Prueba:
printf ''12 1234 1
12345678 1 123
1234 123456 123456
'' > file
Comandos de prueba:
mycolumn file
mycolumn <file
mycolumn - <file
Salida para todos:
12 1234 1
12345678 1 123
1234 123456 123456
Ver también:
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:]]*$,,''
}
EJEMPLO DE EJECUCIONES
$ 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 en: https://github.com/gdbtek/linux-cookbooks/blob/master/libraries/util.bash