5

Я определяю список в bash следующим образом:

list="element1 element_2 my_element_3 element04"

и я хочу сделать цикл, где я перебираю все возможные комбинации пар. В Perl я использовал бы while/foreach со смещением в списке, например так:

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

Я не хочу, чтобы один и тот же элемент в паре, и меня не заботит порядок пар, поэтому, если список "AB C", результат должен быть:

A - B
A - C
B - C

Как я могу сделать эквивалент в Bash?

3 ответа3

9

Кажется, самый простой подход - использовать позиционные параметры.

set -- value1 value2 "value with spaces"
for a; do
    shift
    for b; do
        printf "%s - %s\n" "$a" "$b"
    done
done
1

Другой способ подумать о вашей проблеме: если у вас есть (i, j) индексы для каждого элемента в вашем списке, вас будет интересовать только набор элементов выше (или ниже) диагонали (то есть, где i> j) ,

Если вам нужны все комбинации, вам нужно только проверить, где я!= У.

Я хотел сделать аналогичную вещь: сгенерировать все возможные заказы из 4 предметов. For циклов, вложенных на глубину 4, это будет не очень красиво, и элегантное условное выражение не пришло в голову, но вот это решение:

$ 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

вывести вывод на стандартный вывод, трубу отсортировать -u

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .