У меня есть следующее:
for i in {2..10} do echo "output: $i" done
Он создает пучок строк output: 2
, output: 3
и так далее.
Однако, попробуйте запустить следующее:
max=10 for i in {2..$max} do echo "$i" done
выдает следующее:
output: {2..10}
Как я могу заставить компилятор понять, что он должен обрабатывать $max как другой конец массива, а не часть строки?
Расширение скобки, {x..y} выполняется перед другими расширениями, поэтому вы не можете использовать это для последовательностей переменной длины.
Вместо этого используйте метод seq 2 $max
, как указано mobrule.
Итак, для вашего примера это будет:
max=10
for i in `seq 2 $max`
do
echo "$i"
done
seq
для подсчета и приращения чисел в цикле for, поэтому рекомендуется избегать использования seq
. Эта команда оставлена для совместимости со старым bash. Встроенные команды достаточно быстрые. for (( EXP1; EXP2; EXP3 )) ...
for (( ... ))
- это не POSIX, и это означает, например, что он не будет работать из коробки на вещах, подобных Alpine Linux. seq
делает.
Попробуйте версию арифметического выражения for
:
max=10
for (( i=2; i <= $max; ++i ))
do
echo "$i"
done
Это доступно в большинстве версий bash и должно быть совместимо с оболочкой Bourne (sh).
#!/bin/sh
.
Настройте цикл вручную:
i=0 max=10 while [ $i -lt $max ] do echo "output: $i" true $(( i++ )) done
Если вам не нужно полностью POSIX, вы можете использовать арифметику для цикла:
max=10 for (( i=0; i < max; i++ )); do echo "output: $i"; done
Или используйте jot (1) в BSD-системах:
for i in $( jot 0 10 ); do echo "output: $i"; done
true $(( i++ ))
работает не во всех случаях, поэтому наиболее переносимым будет true $((i=i+1))
.
Доступна ли команда seq
в вашей системе?
for i in `seq 2 $max`
do
echo "output: $i"
done
ИЗМЕНИТЬ: Нет seq
? Тогда как насчет бедного человека seq
с perl
?
seq=`perl -e "\$,=' ';print 2..$max"`
for i in seq
do
echo "output: $i"
done
Смотрите эти кавычки.
Здесь более одного способа сделать это.
max=10
for i in `eval "echo {2..$max}"`
do
echo "$i"
done
eval
будет оценивать все, что вы установили для max
. Рассмотрим max="2}; echo ha; #"
, затем замените echo ha
чем-то более разрушительным.
Это способ:
Bash:
max=10
for i in $(bash -c "echo {2..${max}}"); do echo $i; done
Вышеупомянутый способ Bash будет работать и для ksh
и zsh
, когда bash -c
заменяется на ksh -c
или zsh -c
соответственно.
Примечание: for i in {2..${max}}; do echo $i; done
работает в zsh
и ksh
.
Все они выполняют {1..8}
и должны быть POSIX. Они также не сломаются, если вы
поместите условный continue
в цикл. Канонический путь:
f=
while [ $((f+=1)) -le 8 ]
do
echo $f
done
Другой способ:
g=
while
g=${g}1
[ ${#g} -le 8 ]
do
echo ${#g}
done
а другой:
set --
while
set $* .
[ ${#} -le 8 ]
do
echo ${#}
done
Здесь он работал на MAC-OS // Он включает пример даты BSD, как увеличивать и уменьшать дату также
for ((i=28; i>=6 ; i--));
do
dat=`date -v-${i}d -j "+%Y%m%d"`
echo $dat
done
как насчет
max=10
for i in `eval echo {2..$max}`
do
echo $i
done
Вам нужен явный вызов eval для переоценки {} после замены переменной
Ну, так как у меня не было команды seq
, установленной в моей системе (Mac OS 10.6.1), я вместо этого использовал цикл while
:
max=5 i=1 while [ $max -gt $i ] do (stuff) done
* пожимает плечами * Все, что работает.