Расширение диапазона фигурных скобок трех переменных

Я не уверен, что использовал правильную терминологию в заголовке и в этом вопросе, поэтому, пожалуйста, отредактируйте ее, если она неверна.

В сценарии bash у меня есть три массива: dirs, files и extensions. Как я могу сделать все комбинации строк, которые содержат значение от dirs, затем files, а затем extensions?

У меня вообще нет опыта работы с Bash, но я попробовал это, чтобы увидеть, смогу ли я добиться этого всего с двумя массивами:

$ echo ${dirs[@]}
a b
$ echo ${files[@]}
c d
$ echo ${dirs[@]}{${files[@]}}
a bc d

Результат, который я хочу получить из этого примера, ac bc ad bd

РЕДАКТИРОВАТЬ: я полностью испортил пример и просто исправил его, если вам интересно, что произошло.


person gsingh2011    schedule 19.01.2013    source источник


Ответы (3)


Вы не можете сделать это с синтаксисом {foo,bar}; bash расширяет его, только если видит буквальные запятые между фигурными скобками. (Я полагаю, вы могли бы использовать eval, но это приносит свой беспорядок.)

Просто используйте циклы:

for dir in "${dirs[@]}"; do
    for file in "${files[@]}"; do
        for ext in "${extensions[@]}"; do
            echo "$dir$file$ext"
        done
    done
done
person Eevee    schedule 19.01.2013

Это вдохновлено ответом @Suku, но использует расширение в стиле {a,b,c} вместо {a..c}:

$ dirs=(this/ that/)
$ files=(a b c)
$ extensions=(.c .h)
$ saveIFS=$IFS
$ IFS=,
$ eval echo "{${dirs[*]}}{${files[*]}}{${extensions[*]}}"
this/a.c this/a.h this/b.c this/b.h this/c.c this/c.h that/a.c that/a.h that/b.c that/b.h that/c.c that/c.h
$ IFS=$saveIFS

Обратите внимание, что, как и почти все, что связано с eval, это может привести к катастрофическому сбою, если какое-либо из значений массива имеет неправильные метасимволы. Если это вызывает беспокойство, вместо этого используйте ответ @Eevee.

person Gordon Davisson    schedule 19.01.2013

Следующее будет работать во всех условиях, где выполняются условия расширения скобок

$ dirs=(a b)
$ files=(c d)

$ eval echo {${dirs[0]}..${dirs[$((${#dirs[@]}-1))]}}{${files[0]}..${files[$((${#files[@]}-1))]}}
ac ad bc bd

Для большего понимания:

$ A=`echo {${dirs[0]}..${dirs[$((${#dirs[@]}-1))]}}`
$ B=`echo {${files[0]}..${files[$((${#files[@]}-1))]}}`
$ echo $A$B
{a..b}{c..d}
$ eval echo $A$B
ac ad bc bd
person Suku    schedule 19.01.2013
comment
Это работает только в том случае, если массивы содержат последовательные последовательности букв - это работает для примера в вопросе, но, вероятно, не для реального приложения. - person Gordon Davisson; 19.01.2013
comment
Это будет работать во всех условиях, где выполняются условия расширения скобки. Если входные данные gsingh2011 удовлетворяют условиям раскрытия фигурных скобок, то все в порядке. Другие способы лучше использовать для циклов. Также он пометил вопрос brace-expansion, и поэтому я думаю, что это ему поможет. - person Suku; 19.01.2013
comment
@gsingh2011 . Всегда старайтесь принять ответ, который удовлетворил ваше требование. Баллы - это как мотивация для всех, кто активно здесь отвечает. Таким образом, этот поток можно считать завершенным. - person Suku; 19.01.2013