Сценарий оболочки "для" синтаксиса цикла - PullRequest
175 голосов
/ 18 сентября 2009

Я получил на работу следующее:

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 как другой конец массива, а не как часть строки?

Ответы [ 11 ]

214 голосов
/ 18 сентября 2009

Расширение скобки, {x..y} выполняется перед другими расширениями, поэтому вы не можете использовать это для последовательностей переменной длины.

Вместо этого используйте метод seq 2 $max как пользователь моб указанный .

Итак, для вашего примера это будет:

max=10
for i in `seq 2 $max`
do
    echo "$i"
done
67 голосов
/ 18 сентября 2009

Попробуйте версию с арифметическим выражением for:

max=10
for (( i=2; i <= $max; ++i ))
do
    echo "$i"
done

Это доступно в большинстве версий bash и должно быть совместимо с Bourne shell (sh).

27 голосов
/ 18 сентября 2009

Шаг цикла вручную:

i=0
max=10
while [ $i -lt $max ]
do
    echo "output: $i"
    true $(( i++ ))
done

Если вам не требуется полностью POSIX, вы можете использовать арифметику для цикла:

max=10
for (( i=0; i &lt max; i++ )); do echo "output: $i"; done

Или используйте jot (1) в системах BSD:

for i in $( jot 0 10 ); do echo "output: $i"; done
9 голосов
/ 18 сентября 2009

Существует более одного способа сделать это.

max=10
for i in `eval "echo {2..$max}"`
do
    echo "$i"
done
8 голосов
/ 18 сентября 2009

Если в вашей системе доступна команда seq:

for i in `seq 2 $max`
do
  echo "output: $i"
done

Если нет, тогда используйте seq бедняка с perl:

seq=`perl -e "\$,=' ';print 2..$max"`
for i in $seq
do
  echo "output: $i"
done

Смотрите эти кавычки.

4 голосов
/ 21 июля 2018

Мы можем повторять цикл как программирование на Си.

#!/bin/bash
for ((i=1; i<=20; i=i+1))
do 
      echo $i
done
4 голосов
/ 12 июля 2015

Это способ:
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.

2 голосов
/ 06 декабря 2013

Здесь это работает на Mac OS X.

Включает в себя пример даты BSD, как увеличить или уменьшить дату также:

for ((i=28; i>=6 ; i--));
do
    dat=`date -v-${i}d -j "+%Y%m%d"` 
    echo $dat
done
2 голосов
/ 18 сентября 2009

Ну, поскольку в моей системе не установлена ​​команда seq (Mac OS X v10.6.1 (Snow Leopard)), я вместо этого использовал цикл while:

max=5
i=1

while [ $max -gt $i ]
do
    (stuff)
done

* Пожимает плечами * Все, что работает.

1 голос
/ 19 декабря 2015

Все они делают {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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...