Chciałbym uzyskać tekst w formacie tabeli. Próbowałem powtórzyć elementy tablicy za pomocą '\ t', ale było źle wyrównane.
Mój kod
for((i=0;i<array_size;i++));
do
echo stringarray[$i] $'\t' numberarray[$i] $'\t' anotherfieldarray[$i]
done;
Moje dzieło
a very long string.......... 112232432 anotherfield
a smaller string 123124343 anotherfield
Pożądane wyjście
a very long string.......... 112232432 anotherfield
a smaller string 123124343 anotherfield
%-10s
generujemy ciągi wyrównane do lewej o długości 10Użyj polecenia kolumny:
column -t -s' ' filename
źródło
%s
specyfikator formatu przyjmuje odstępy jako separator. W takim przypadku żadna z odpowiedzi tutaj nie zadziała. Jestem zdumiony, że wielokrotnie mówisz o pożądanym wyniku, gdy analizowanie (przy użyciu dowolnego narzędzia) zależy od ogranicznika wejścia.cat /etc/fstab | sed -r 's/\s+/ /g' | column -t -s' '
Aby uzyskać dokładnie takie same wyniki, jak potrzebujesz, musisz sformatować plik w następujący sposób:
A potem używając:
$ column -t -s $'\t' FILE a very long string.......... 112232432 anotherfield a smaller string 123124343 anotherfield
źródło
$
w$'\t'
robi?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:]]*$,,' }
PRÓBNE PRZEBIEGI
$ 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 pod adresem : https://github.com/gdbtek/linux-cookbooks/blob/master/libraries/util.bash
źródło
-e
parametr w poleceniach echo, aby myślniki zostały poprawnie wydrukowane.To łatwiejsze niż się zastanawiasz.
Jeśli pracujesz również z plikiem oddzielonym średnikiem i nagłówkiem:
$ (head -n1 file.csv && sort file.csv | grep -v <header>) | column -s";" -t
Jeśli pracujesz z tablicą (używając tabulatora jako separatora):
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
źródło
awk
rozwiązanie obsługujące stdinPonieważ
column
nie jest to POSIX, może to być: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 [ "$1" = - ]; then rm "$file" fi )
Test:
printf '12 1234 1 12345678 1 123 1234 123456 123456 ' > file
Polecenia testowe:
Wyjście dla wszystkich:
Zobacz też:
źródło
if [ "$file" = - ]; then
końcu powinno byćif [ "$1" = - ]; then
. Przy obecnym kodzie nigdy nie czyścisz plików tymczasowych.Nie jestem pewien, gdzie to uruchomiłeś, ale kod, który opublikowałeś, nie wygeneruje danych wyjściowych, które dałeś, przynajmniej nie w bashu, który znam.
Spróbuj tego zamiast tego:
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'
Zwróć uwagę, że używam znaku separatora grupy (1d) w środku tabulatora, ponieważ jeśli otrzymujesz te tablice z pliku, mogą one zawierać tabulatory.
źródło
Na wypadek, gdyby ktoś chciał to zrobić w PHP, zamieściłem streszczenie na Githubie
https://gist.github.com/redestructa/2a7691e7f3ae69ec5161220c99e2d1b3
po prostu zadzwoń:
$output = $tablePrinter->printLinesIntoArray($items, ['title', 'chilProp2']);
może zajść potrzeba dostosowania kodu, jeśli używasz wersji php starszej niż 7.2
po tym wywołaniu echo lub writeLine w zależności od środowiska.
źródło
Poniższy kod został przetestowany i robi dokładnie to, o co proszono w pierwotnym pytaniu.
Parametry:% 30s Kolumna 30 znaków i tekst wyrównany do prawej. % 10d notacja całkowita,% 10s również będzie działać. Dodano wyjaśnienie zawarte w komentarzach do kodu.
stringarray[0]="a very long string.........." # 28Char (max length for this column) numberarray[0]=1122324333 # 10digits (max length for this column) anotherfield[0]="anotherfield" # 12Char (max length for this column) stringarray[1]="a smaller string....." numberarray[1]=123124343 anotherfield[1]="anotherfield" printf "%30s %10d %13s" "${stringarray[0]}" ${numberarray[0]} "${anotherfield[0]}" printf "\n" printf "%30s %10d %13s" "${stringarray[1]}" ${numberarray[1]} "${anotherfield[1]}" # a var string with spaces has to be quoted printf "\n Next line will fail \n" printf "%30s %10d %13s" ${stringarray[0]} ${numberarray[0]} "${anotherfield[0]}" a very long string.......... 1122324333 anotherfield a smaller string..... 123124343 anotherfield
źródło