Reputation: 304
I have 2 arrays, where artists
includes music artist names and songs
includes song titles. What I want to do is output each in an alternating manner so that I get array1[1] - array2[1], array1[2] - array2[2]...
, or:
Chelsea Wolfe - Mer
Pavement - Embassy Row
Black Math Horseman - Torment of the Metals
...
Here is what I have now, with example arrays provided. The actual arrays are the result of echoed and processed (with grep) curl command substitutions, so I'm not sure if they contain double quotes, but the output I get is same as the example provided here. [Edit: This is incorrect. As I mentioned in a comment to John1024 below, the actual arrays I'm using have newlines after each element.]
I know this is wrong, and I know why (because I'm telling Bash to "print all elements of artists
then all elements of songs
"), I just don't know the solution.
artists=("Chelsea Wolfe" "Pavement" "Black Math Horseman" "Marriages" "Chelsea Wolfe")
songs=("Mer" "Embassy Row" "Torment of the Metals" "The Liar" "The Waves have Come")
IFS=$'\n'
for ((i=0;i<"${#artists[@]}";++i));
do
printf "%s\n" "${artists[@]} - ${songs[@]}"
done
[Edit: I removed the useless unassigned `OIFS` variable that was here. See my comment to glenn jackman below.]
Would it make sense to somehow combine them in the alternating way I want, and then have that array print, or is there a simpler solution?
Upvotes: 2
Views: 527
Reputation: 113844
Let's eliminate the IFS
commands and make some small changes to the printf
command:
artists=("Chelsea Wolfe" "Pavement" "Black Math Horseman" "Marriages" "Chelsea Wolfe")
songs=("Mer" "Embassy Row" "Torment of the Metals" "The Liar" "The Waves have Come")
for ((i=0;i<"${#artists[@]}";++i));
do
printf "%s - %s\n" "${artists[$i]}" "${songs[$i]}"
done
This produces the output:
Chelsea Wolfe - Mer
Pavement - Embassy Row
Black Math Horseman - Torment of the Metals
Marriages - The Liar
Chelsea Wolfe - The Waves have Come
We can get the columns to line up by changing the printf line to:
printf "%-20s - %s\n" "${artists[$i]}" "${songs[$i]}"
With that change, the output becomes:
Chelsea Wolfe - Mer
Pavement - Embassy Row
Black Math Horseman - Torment of the Metals
Marriages - The Liar
Chelsea Wolfe - The Waves have Come
Suppose, as per the comments, that the elements have trailing newlines:
artists=($'Chelsea Wolfe\n' $'Pavement\n' $'Black Math Horseman\n' $'Marriages\n' $'Chelsea Wolfe')
songs=($'Mer\n' $'Embassy Row\n' $'Torment of the Metals\n' $'The Liar\n' $'The Waves have Come')
We can remove the those newline characters using bash suffix removal:
for ((i=0;i<"${#artists[@]}";++i));
do
printf "%s - %s\n" "${artists[$i]%$'\n'}" "${songs[$i]%$'\n'}"
done
The output is still:
Chelsea Wolfe - Mer
Pavement - Embassy Row
Black Math Horseman - Torment of the Metals
Marriages - The Liar
Chelsea Wolfe - The Waves have Come
Upvotes: 2
Reputation: 246827
We can do this with a paste
and some process substitution:
$ paste <(printf "%s\n" "${artists[@]}") <(printf "%s\n" "${songs[@]}")
Chelsea Wolfe Mer
Pavement Embassy Row
Black Math Horseman Torment of the Metals
Marriages The Liar
Chelsea Wolfe The Waves have Come
That's a bit messy, let's pretty it up with column
:
$ paste <(printf "%s\n" "${artists[@]}") <(printf "%s\n" "${songs[@]}") | column -t -s $'\t' -o " - "
Chelsea Wolfe - Mer
Pavement - Embassy Row
Black Math Horseman - Torment of the Metals
Marriages - The Liar
Chelsea Wolfe - The Waves have Come
Upvotes: 2
Reputation: 203615
The reason you're struggling is that the shell is an environment from which to call tools, not a tool for manipulating text, and so it's extremely difficult to write shell scripts to manipulate text. The guys who invented shell to call UNIX tools also invented the UNIX tool awk
for the shell to call to manipulate text so just use it:
$ cat tst.awk
BEGIN {
FS=","; OFS=" - "
split("Chelsea Wolfe,Pavement,Black Math Horseman,Marriages,Chelsea Wolfe",artists)
split("Mer,Embassy Row,Torment of the Metals,The Liar,The Waves have Come",songs)
for (i=1;i in artists;i++) {
print artists[i], songs[i]
}
}
$ awk -f tst.awk
Chelsea Wolfe - Mer
Pavement - Embassy Row
Black Math Horseman - Torment of the Metals
Marriages - The Liar
Chelsea Wolfe - The Waves have Come
Upvotes: 0