2012-03-28 3 views
22

Вот 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} напрямую?

+1

Ваш пример сценария будет работать в обоих ksh93 и Zsh , –

ответ

43

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

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

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

+0

Не работает для меня 'test.sh: строка 1: ((: i <=: синтаксическая ошибка: предполагается, что операнд (токен ошибки« <= »)' – Temak

+0

@Temak вы используете 'bash'? #!/bin/bash' или '#!/bin/sh'? – jordanm

+0

@jordann, файл содержит только эти 3 строки. Я использую GNU bash, версия 4.3.11 (1) -release (x86_64-pc- linux-gnu). Я запускаю скрипт 'bash test.sh' – Temak

18

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

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

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

Резюме: Bash мерзко.

+1

Хех, +1 за ответ, -0,5 за подлый. –

+1

@glennjackman: Ого, ты говоришь, что бесчисленные расширения и избегающие правила Баша не мерзкие? –

+0

Я чувствую себя грязным за то, что сказал +1 на ответ, включающий 'eval'. Re: vile: 'bash' не мерзкий, но это немного похоже на алкоголь с пряным спиртом. Некоторым людям это нравится, но сначала трудно задыхаться, и чем больше вы это делаете, тем меньше вас беспокоит. – Sorpigal

11

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

for i in `seq 1 $1` 

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

for((i=1;i<=$1;i++)) 
+0

Цикл стиля C предпочтительнее внешней команды seq. – jordanm

+0

@jordanm Это хорошая идея. – kev

+0

wery good, с seq вы можете изменить шаг! –

1

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

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

0

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

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

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

for i in ${range[@]};do echo $i;done 
1 
2 
3 
Смежные вопросы