Jak wydrukować zmienne wielowierszowe w kolumnach obok siebie w bash?

12

Mam dwie zmienne, które zawierają informacje o wielu wierszach i chcę je kolumować.

varA zwroty

Aug 01
Aug 04
Aug 16
Aug 26

i varBwraca

04:25
07:28
03:39
10:06

jeśli wydrukuję obie zmienne, zwraca

Aug01
Aug04
Aug16
Aug26
04:25
07:28
03:39
10:06

To, co chcę zrobić, to:

Aug01 04:25
Aug04 07:28
Aug16 03:39
Aug26 10:06

Jestem nowy w używaniu Linuksa i byłbym wdzięczny za porady.

BNairb
źródło
Podaj kod bash, którego użyłeś podczas próby wydrukowania dwóch zmiennych. Dzięki temu możemy zobaczyć, co zrobiłeś źle podczas próby.
Bernard Wei,

Odpowiedzi:

22

Poznaj pasteczęść wstępnie zainstalowanych narzędzi GNU :

$ paste <(printf %s "$varA") <(printf %s "$varB")
Aug 01  04:25
Aug 04  07:28
Aug 16  03:39
Aug 26  10:06

pastepobiera pliki, a nie zmienne jako dane wejściowe, więc użyłem bashprocesu podstawiania i właśnie wydrukowałem zawartość zmiennej printf. Domyślnym ogranicznikiem między kolumnami jest to TAB, że można to zmienić za pomocą -dopcji, np. paste -d" "Dla pojedynczego znaku spacji. Aby dowiedzieć się więcej, zapoznaj pastesię z instrukcją online lub uruchom info '(coreutils) paste invocation'.

deser
źródło
1
@BNairb Jeśli ta odpowiedź rozwiązała problem, poświęć chwilę i zaakceptuj go , klikając znacznik wyboru po lewej stronie. To oznacza pytanie jako odpowiedź i jest to sposób wyrażania podziękowań na stronach Stack Exchange.
deser
7

Jeśli chcesz po prostu wyświetlać zmienne tekstowe obok siebie, @dessert ma najprostsze (najlepsze?) Rozwiązanie print. Jednak jeśli chcesz mieć możliwość manipulowania każdym kawałkiem osobno, możesz łatwo przekształcić zmienne w tablice, a następnie przejść przez to.

#!/bin/bash

# declare the multi-line variables
var1="1
2
3
4"
var2="a
b
c
d"

# backup internal field separator to be safe
IFSave=$IFS

# set IFS to newline so vars will use newline to split into array
IFS=$'\n'

# split variables into array
foo=($var1)
bar=($var2)

#restore IFS to original value to be safe
IFS=$IFSave

# loop array foo, and cross reference key in array bar
for i in "${!foo[@]}"; do 
  printf "${foo[$i]} : ${bar[$i]}\n"
done

# you can allso now print single corresponding lines:
line=3

let id=$line-1 # arrays start at 0, so need to remove one

printf "\nPrinting line number $line\n"
printf "${foo[$id]} : ${bar[$id]}\n"
Joshua Besneatte
źródło
4

Możesz to zrobić za pomocą narzędzia POSIX pr:

varA='Aug 01
Aug 04
Aug 16
Aug 26'
varB='04:25
07:28
03:39
10:06'
pr -2 -t <<eof
$varA
$varB
eof

Wynik:

Aug 01                              04:25
Aug 04                              07:28
Aug 16                              03:39
Aug 26                              10:06

Lub dla pojedynczej karty:

pr -2 -t -s

Lub dla pojedynczego miejsca:

pr -2 -t -s' '

http://pubs.opengroup.org/onlinepubs/9699919799/utilities/pr.html

Lub columnz util-linuxpakietu:

column -c 20 <<eof
$varA
$varB
eof
Steven Penny
źródło
3

Jeśli chcesz uniknąć zewnętrznych narzędzi i zrobić to natywnie w powłoce, możesz użyć readosobnych ciągów deskryptorów plików / tutaj dla każdej zmiennej:

while IFS= read -r -u3 a && read -r -u4 b; do 
  printf '%s\t%s\n' "$a" "$b"
done 3<<<"$varA" 4<<<"$varB"
Aug 01  04:25
Aug 04  07:28
Aug 16  03:39
Aug 26  10:06

Mimo że używanie powłoki do przetwarzania tekstu jest często uważane za złą praktykę, może być usprawiedliwione w przypadku, gdy masz już dane w zmiennych powłoki.

steeldriver
źródło