Использование переменной в диапазоне расширения фигурной скобки, передаваемой в цикл for - PullRequest
46 голосов
/ 28 марта 2012

Вот myscript.sh

#!/bin/bash
for i in {1..$1};
do
    echo $1 $i;
done

Если я запускаю myscript.sh 3, вывод будет

3 {1..3}

вместо

3 1
3 2
3 3

Очевидно, $3 содержит правильное значение, так почему же for i in {1..$1} не ведет себя так, как если бы я написал for i in {1..3} напрямую?

Ответы [ 5 ]

67 голосов
/ 29 марта 2012

Вы должны использовать цикл for в стиле C, чтобы выполнить это:

for ((i=1; i<=$1; i++)); do
   echo $i
done

Это позволяет избежать внешних команд и неприятных операторов eval.

27 голосов
/ 28 марта 2012

Поскольку раскрытие фигурной скобки происходит до раскрытия переменных.http://www.gnu.org/software/bash/manual/bashref.html#Brace-Expansion.

Если вы хотите использовать фигурные скобки, вы можете сделать что-то мрачное, например:

for i in `eval echo {1..$1}`;
do
    echo $1 $i;
done

Краткое описание: Bash - это мерзко.

15 голосов
/ 28 марта 2012

Вы можете использовать команду seq:

for i in `seq 1 $1`

Или вы можете использовать стиль C for...loop:

for((i=1;i<=$1;i++))
2 голосов
/ 21 января 2015

Вот способ расширения переменных внутри фигурных скобок без eval :

end=3
declare -a 'range=({'"1..$end"'})'

Теперь у нас есть хороший массив чисел:

for i in ${range[@]};do echo $i;done
1
2
3
1 голос
/ 04 февраля 2014

Я знаю, что вы упомянули bash в заголовке, но я бы добавил, что 'for i in {$ 1 .. $ 2}' работает так, как задумано в zsh.Если в вашей системе установлен zsh, вы можете просто изменить свой shebang на zsh.

Использование zsh с примером 'for i in {$ 1 .. $ 2}' также имеет дополнительное преимущество: $ 1 может быть меньше $ 2.и это все еще работает, что-то, что потребовало бы немало хлопот, если бы вы хотели такой гибкости с циклом for в стиле C.

...