Wie drucke ich mehrzeilige Variablen in nebeneinander angeordneten Spalten (Bash)?

11

Ich habe zwei Variablen, die mehrzeilige Informationen enthalten, und ich möchte sie spalten.

varA kehrt zurück

Aug 01
Aug 04
Aug 16
Aug 26

und varBkehrt zurück

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

Wenn ich beide Variablen drucke, gibt es zurück

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

Was ich tun möchte, ist Folgendes:

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

Ich bin neu in Linux und würde mich über Ratschläge freuen, danke.

BNairb
quelle
Bitte geben Sie den Bash-Code an, den Sie beim Drucken der beiden Variablen verwendet haben. Auf diese Weise können wir sehen, was Sie bei Ihrem Versuch falsch gemacht haben.
Bernard Wei

Antworten:

22

Treffen Sie paste, Teil der vorinstallierten GNU-Kerndienstprogramme :

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

pasteNimmt Dateien und keine Variablen als Eingabe, also habe ich bashProcess Substitution verwendet und nur den Variableninhalt mit gedruckt printf. Das Standardtrennzeichen zwischen Spalten ist TAB, dass Sie dies mit der -dOption ändern können , z. B. paste -d" "für ein einzelnes Leerzeichen. Weitere pasteInformationen finden Sie im Online-Handbuch oder unter Ausführen info '(coreutils) paste invocation'.

Dessert
quelle
1
@BNairb Wenn diese Antwort Ihr Problem gelöst hat, nehmen Sie sich bitte einen Moment Zeit und akzeptieren Sie sie, indem Sie auf das Häkchen links klicken. Dadurch wird die Frage als beantwortet markiert und auf die Stack Exchange-Websites wird der Dank ausgesprochen.
Nachtisch
7

Wenn Sie nur die Textvariablen nebeneinander anzeigen möchten, bietet @dessert die einfachste (beste?) Lösung print. Wenn Sie jedoch in der Lage sein möchten, jedes Stück einzeln zu manipulieren, können Sie die Vars stattdessen einfach in Arrays konvertieren und diese durchlaufen.

#!/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
quelle
3

Wenn Sie externe Dienstprogramme vermeiden und dies nativ in der Shell tun möchten, können Sie readfür jede Variable separate Dateideskriptoren / here-Zeichenfolgen verwenden:

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

Obwohl es oft als schlechte Praxis angesehen wird, die Shell für die Textverarbeitung zu verwenden, kann dies für den Fall entschuldigt werden, dass Sie die Daten bereits in Shell-Variablen haben.

Steeldriver
quelle
3

Sie können dies mit dem POSIX-Tool tun 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

Ergebnis:

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

Oder für eine einzelne Registerkarte:

pr -2 -t -s

Oder für einen einzelnen Raum:

pr -2 -t -s' '

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

Oder mit columnaus dem util-linuxPaket:

column -c 20 <<eof
$varA
$varB
eof
Steven Penny
quelle