-1

Get two lists from two variables and combine side by side into one variable.

Suppose you echo "$var1" you get this output:

a
b
c
d

Suppose you echo $var2 you get this output:

1
2
3
4

I want $var3 to have this exact output:

a 1
b 2
c 3
d 4

How do you do this? And if you are asking why I want this, when you assign a variable a command or multiple commands, the first command must start and end, then the second command must start and end such that varx=(command1 && command2) would provide:

a
b
c
d
1
2
3
4

Also this must be accomplished without file input or output. I forgot to add, do not assume the lists are static. In fact, assume the opposite, the lists are dynamic. That is to say one command generates one list and another generates another list. So part of the problem is making sure the output is in sync especially with script buggy software like apt. It gets a little confusing because both apt, aptitude and apt-rdepends can show packages and rdepends (except maybe aptitude). They all different speeds and levels of bugginess, apt being the most buggy. It would be nice to have a function to test program speed (which of the 3 is fastest in showing packages or rdependencies). Anyways, I worked around the problem by using one program to fetch the dependencies (therefore create static list) and another to show the package name and size. Before I was trying to list rdepends and show at the same time, but with different commands thus leading to all sorts of fun problems including sync :) I know see how stupid that was.

As promised here is the script (the 1st was the subject of this question):

RDEPENDS version

ps -A &>> Distro1Analysis.txt && sudo service --status-all &>> Distro1Analysis.txt && \
for z in $(dpkg -l | awk '/^[hi]i/{print $2}' | grep -v '^lib'); do \
printf "\n$z:" && \
aptitude show $z | grep -E 'Uncompressed Size' && \
result=$(apt-rdepends 2>/dev/null $z | grep -v "Depends")
final=$(apt show 2>/dev/null $result | grep -E "Package|Installed-Size" | sed "/APT/d;s/Installed-Size: //");
if [[ (${#final} -le 700) ]]; then echo $final; else :; fi done &>> Distro1Analysis.txt

DEPENDS

ps -A &>> Distro1Analysis.txt && sudo service --status-all &>> Distro1Analysis.txt && \
for z in $(dpkg -l | awk '/^[hi]i/{print $2}' | grep -v '^lib'); do \
printf "\n$z:" && \
aptitude show $z | grep -E 'Uncompressed Size' && \
printf "\n" && \
apt show 2>/dev/null $(aptitude search '!~i?reverse-depends("^'$z'$")' -F "%p" | \
sed 's/:i386$//') | grep -E 'Package|Installed-Size' | sed '/APT/d;s/^.*Package:/\t&/;N;s/\n/ /'; done &>> Distro1Analysis.txt

Both scripts work, however could be written more clearly and optimized to work much faster. However both scripts teach nevertheless. Also, although, I fixed the scripts so they function, to keep compact, I opted not to put into two lists as originally sought; due how commands were originally spitting out the output.

codeforester
  • 39,467
  • 16
  • 112
  • 140
  • Welcome to Stackoverflow. How are you getting $var1 to have multi-line values? Array? Answer will depend on that. – Mamun Apr 11 '20 at 21:49
  • Cross-site dupe: [How to print multiline variables in side-by-side columns](https://askubuntu.com/q/1066396/615697) – codeforester Apr 12 '20 at 02:06
  • If a solution worked for you, the right way to acknowledge that is to accept the answer, not changing the title to "Solved". Please see [What should I do when someone answers my question?](https://stackoverflow.com/help/someone-answers). – codeforester Apr 12 '20 at 06:13
  • 1
    This question needs more focus. Please edit the question to limit it to a specific problem with enough detail to identify an adequate answer. Avoid asking multiple distinct questions at once. See the [How to Ask](https://stackoverflow.com/help/how-to-ask) page for help clarifying this question. – rtx13 Apr 12 '20 at 11:53

3 Answers3

2
var3=$(paste -d " " -- <(echo "$var1") <(echo "$var2"))

The -d " " sets the delimiter to a whitespace instead of tab.

Quasímodo
  • 3,812
  • 14
  • 25
  • Good. I didn't mention but part of the problem is making sure both arrays are synced, because they are generated from two seperate commands. So despite the above working for a static lists, it does not work for dynamic ones. – user995381 Apr 12 '20 at 03:35
1

You can use pr as well:

var3=$(pr -tm -s' ' <(printf '%s' "$var1") <(printf '%s' "$var2"))
  • -t -> don't print header
  • -m -> merge files
  • -s char -> use char as the separator

More simply, using a heredoc and -2 option to signify two column output:

var3=$(pr -2ts' ' <<EOF
$var1
$var2
EOF
)

See also:

codeforester
  • 39,467
  • 16
  • 112
  • 140
0

Pure bash solution using arrays:

$ var1=( a b c d )
$ var2=( 1 2 3 4 )
$ for ((i=0;i<${#var1[*]};++i)) { var3+=( "${var1[i]} ${var2[i]}" ); }
$ declare -p var3
declare -a var3=([0]="a 1" [1]="b 2" [2]="c 3" [3]="d 4")

... starting from strings, you can convert into arrays like this:

$ var1string='a
b
c
d'
$ var2string='1
2
3
4'
$ IFSSAVE=$IFS
$ IFS=$'\n'  # use newline to split strings into arrays
$ var1=( $var1string )
$ var2=( $var2string )
$ IFS=$IFSSAVE

... and proceed with the for loop from the initial arrays solution.

rtx13
  • 2,580
  • 1
  • 6
  • 22
  • 1
    @user995381 Can you clarify what didn't work? What's bad about loops? You asked for 'this must be accomplished without file input or output'—please note both other solutions use `<(...)` process substitution which requires file I/O... – rtx13 Apr 12 '20 at 11:45