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
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.
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
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.
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
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
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: