Comment imprimer des variables multilignes dans des colonnes côte à côte dans bash?

12

J'ai deux variables qui contiennent des informations sur plusieurs lignes et je veux les colonnes.

varA Retour

Aug 01
Aug 04
Aug 16
Aug 26

et varBretourne

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

si j'imprime les deux variables, il retourne

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

Ce que je veux faire est le suivant:

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

Je suis novice dans l'utilisation de Linux et j'apprécierais quelques conseils.

BNairb
la source
Veuillez inclure le code bash que vous avez utilisé dans votre tentative d'impression des deux variables. C'est pour que nous puissions voir ce que vous avez fait de mal dans votre tentative.
Bernard Wei

Réponses:

22

Meet paste, qui fait partie des utilitaires GNU core préinstallés :

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

pasteprend des fichiers et non des variables en entrée, j'ai donc utilisé bashla substitution de processus et j'ai simplement imprimé le contenu des variables avec printf. Le délimiteur par défaut entre les colonnes est TAB, vous pouvez le changer avec l' -doption, par exemple paste -d" "pour un seul caractère d'espace. Pour en savoir plus, pasteconsultez le manuel en ligne ou lancez info '(coreutils) paste invocation'.

dessert
la source
1
@BNairb Si cette réponse a résolu votre problème, veuillez prendre un moment et l' accepter en cliquant sur la coche à gauche. Cela marquera la réponse à la question et c'est la façon dont les remerciements sont exprimés sur les sites Stack Exchange.
dessert
7

Si vous voulez simplement afficher les variables de texte côte à côte, @dessert a la solution la plus simple (la meilleure?) À utiliser print. Cependant, si vous souhaitez pouvoir manipuler chaque pièce individuellement, vous pouvez facilement convertir les vars en tableaux à la place et les parcourir.

#!/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
la source
4

Vous pouvez le faire avec l'outil 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

Résultat:

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

Ou pour un seul onglet:

pr -2 -t -s

Ou pour un espace unique:

pr -2 -t -s' '

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

Ou avec columndu util-linuxpackage:

column -c 20 <<eof
$varA
$varB
eof
Steven Penny
la source
3

Si vous vouliez éviter les utilitaires externes et le faire de manière native dans le shell, vous pouvez utiliser readavec des descripteurs de fichiers / chaînes ici pour chaque variable:

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

Bien qu'il soit souvent considéré comme une mauvaise pratique d'utiliser le shell pour le traitement de texte, il peut être excusé dans le cas où vous avez déjà les données dans des variables de shell.

tournevis
la source