I have two variables
VAR1="1 2 3"
VAR2="Bob Tom Kate"
I want to echo something like this but I don't know how to use multiple variables in a loop:
1 for Bob
2 for Tom
3 for Kate
All I can is:
(
for i in $VAR1; do
echo "$i"
done
)
I have two variables
VAR1="1 2 3"
VAR2="Bob Tom Kate"
I want to echo something like this but I don't know how to use multiple variables in a loop:
1 for Bob
2 for Tom
3 for Kate
All I can is:
(
for i in $VAR1; do
echo "$i"
done
)
In zsh:
var1=(1 2 3)
var2=(Bob Tom Kate)
for i j in ${var1:^var2}; do
printf '%q, %q\n' $i $j
done
If those variables may contain empty values:
var1=('' 2 3)
var2=('Bob XIV' Tom '')
for i j in "${(@)var1:^var2}"; do
printf '%q, %q\n' "$i" "$j"
done
(or "${var1[@]:^var2}"
, the point being to get a similar behaviour as with the "$@"
parameter expansion of the Bourne shell, or the "${array[@]}"
of the Korn shell where elements are passed separate and verbatim as if quoted including empty ones)
${a:^b}
is an array zipping parameter expansion operator. There's also the ${a:^^b}
variant which reuses elements of the shorter array if the arrays don't have the same number of elements.
In zsh, best is to avoid dereferencing array elements via their index if possible as that is very inefficient in current versions especially for large arrays, mainly because of the fact zsh doesn't record the size of its arrays, so even though accessing the nth element should be instantaneous as that's indexing in a C array, zsh still needs to check n is not past the end of the arrays for which it still needs to check the n - 1 elements before it.
For looping over 3 or more arrays, you still need to do that though:
n=$#var1
for (( i = 1; i <= n; i++ ))
printf '%q, %q, %q\n' "$var1[i]" "$var2[i]" "$var3[i]"
Which would be orders of magnitudes slower than the equivalent code in ksh93 or even bash.
n=${#var1[@]}
for (( i = 0; i < n; i++ )) {
printf '%q, %q, %q\n' "${var1[i]}" "${var2[i]}" "${var3[i]}"
}
In bash
$ function assoc() { for i in $VAR1; do echo "$i for $1" ; shift; done ; }
$ assoc $VAR2
1 for Bob
2 for Tom
3 for Kate
Transform you variables into arrays and work with them.
#!/bin/bash
VAR1="1 2 3"
VAR2="Bob Tom Kate"
since you have spaces in the original string, then a simple paranthesis will work
arr1=($VAR1)
arr2=($VAR2)
for (( i=0; i<${#arr1[@]}; i++ ))
do
echo ${arr1[$i]} for ${arr2[$i]}
done
This assumes that both your original variables have same number of elements.
If your variables would have a different way of splitting words (commas for example), then you would have to use a different method of splitting string into array.
arr1=($VAR1)
splits $VAR1
on the current value of $IFS
(the default value when bash starts contains space, tab and newline) but will also perform globbing. When using the split+glob operator, you generally want to tune it beforehand. See the What about when you do need the split+glob operator? section at Security implications of forgetting to quote a variable in bash/POSIX shells. In any case, using split+glob in the arguments to echo
doesn't make sense.
– Stéphane Chazelas
Apr 10 '23 at 06:22