6

I define a list in bash like this:

list="element1 element_2 my_element_3 element04"

and I want to do a loop where I iterate through all possible pair combinations. In Perl, I would use a while/foreach with a shift on the list like this:

while (my $element1 = shift (@list)) {
  foreach my $element2 (@list) {
      print "$element1 - $element2\n";
  }
}

I don't want the same element in the pair and don't care about the order of the pairs, so if the list is "A B C", the result should be:

A - B
A - C
B - C

How can I do the equivalent in bash?

3 Answers 3

10

The simplest approach seems to be to use positional parameters.

set -- value1 value2 "value with spaces"
for a; do
    shift
    for b; do
        printf "%s - %s\n" "$a" "$b"
    done
done
3
  • hmmmm, just to clarify, I don't want the same element in the pair and don't care about the order of the pairs, I've edited my question now.
    – 719016
    Aug 2, 2011 at 13:12
  • I just saw the shift in your original question as well. Updated answer to match.
    – jw013
    Aug 2, 2011 at 13:21
  • This for loop looked odd to me. In case others are wondering, like I was (and I've just had to look it up), if no ...in <values> is specified, the loop processes each positional parameter that is set ($1, $2, $3 etc). I mean, it seems obvious now, but there you go. Thank you @jw013 for showing me this feature!
    – qmacro
    Dec 3, 2020 at 8:55
1

Another way to think about your problem is: if you had (i,j) indexes for each item in your list, you would only be interested in the set of items above (or below) the diagonal (ie, where i>j).

If you did want all combinations, then you only have to test where i!=j.

I wanted to do a similar thing: generate all possible orderings of 4 items. For loops nested to a depth of 4 would not be very pretty, and an elegant conditional didn't come to mind, but this solution did:

$ for combo in  {en,fa,sp,ru}{en,fa,sp,ru}{en,fa,sp,ru}{en,fa,sp,ru}; do echo $combo; done | egrep -v 'en.*en|fa.*fa|sp.*sp|ru.*ru' 
enfaspru
enfarusp
enspfaru
ensprufa
enrufasp
enruspfa
faenspru
faenrusp
faspenru
faspruen
faruensp
faruspen
spenfaru
spenrufa
spfaenru
spfaruen
spruenfa
sprufaen
ruenfasp
ruenspfa
rufaensp
rufaspen
ruspenfa
ruspfaen
-2

dump the output to standard out, pipe to sort -u

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.