How to print multiline variables in side-by-side columns in bash?

I have two variables which contain multi-line information and I want to column them.

varA returns

Aug 01
Aug 04
Aug 16
Aug 26

and varB returns

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

if i print both variables, it returns

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

What I want to do is the following:

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

I'm new to using Linux and I would appreciate some advice.


Solution 1:

Meet paste, part of the preinstalled GNU core utilities:

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

paste takes files and not variables as input, so I used bash Process Substitution and just printed the variable content with printf. The default delimiter between columns is TAB, you can change that with the -d option, e.g. paste -d" " for a single space character. To learn more about paste have a look at the online manual or run info '(coreutils) paste invocation'.

Solution 2:

If you just want to simply display the text variables side by side, @dessert has the most simple (best?) solution using print. However if you want to be able to manipulate each piece individually, you could easily convert the vars to arrays instead, and loop through that.

#!/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"

Solution 3:

You can do this with the POSIX tool 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

Result:

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

Or for single tab:

pr -2 -t -s

Or for single space:

pr -2 -t -s' '

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

Or with column from the util-linux package:

column -c 20 <<eof
$varA
$varB
eof