Ответ 1
создать последовательность для управления петлей
for i in $(seq 1 $howmany); do
echo "Welcome";
done
#!/bin/sh
for i in {1..5}
do
echo "Welcome"
done
Будет работать, отображает приветствие 5 раз.
#!/bin/sh
howmany=`grep -c $1 /root/file`
for i in {1..$howmany}
do
echo "Welcome"
done
Не работает! howmany
будет равным 5, так как будет отображаться вывод grep -c
. $1 - параметр 1, который специфичен при запуске script.
Любые идеи?
создать последовательность для управления петлей
for i in $(seq 1 $howmany); do
echo "Welcome";
done
Расширение скобки вычисляется до того, как переменные будут расширены. Вместо этого вам нужен c-стиль для цикла:
for ((i=1;i<=howmany;i++))
do
echo "Welcome"
done
Если целью является просто перебрать номера в диапазоне - как в случае OP - лучший не использовать расширение скобок, но вместо этого используйте bash цикл C-стиля - см. user000001 answer.
Если использование расширения скобки желательно, тем не менее:
Если вам НЕ нужны числа в списке, чтобы иметь префикс или постфикс, используйте утилиту seq
с заменой без кавычек (небольшая caveat: seq
НЕ является утилитой POSIX, но она широко доступна); например.
echo $(seq 3)
→ 1 2 3
; начальный номер 1
подразумевается
echo $(seq -f '%02.f' 3)
→ 01 02 03
- ноль-paddedecho $(seq 2 4)
→ 2 3 4
; явные начальные и конечные номераecho $(seq 1 2 5)
→ 1 3 5
; пользовательский прирост (2
посередине)Если вы нужны номера в списке, чтобы иметь префикс или постфикс, у вас есть несколько вариантов:
seq
с ее опцией -f
для предоставления строки формата printf
-стиля (как указано выше для нулевого заполнения) или чистых bash обходных путей на основе eval
(требуется дополнительная помощь!) или создание массива в цикле, все из которых подробно описаны в этом ответе.awk
или perl
.eval
с переменными, управляющими выражением скобки последовательности:Переменные проверяются заранее, чтобы убедиться, что они содержат десятичные целые числа.
from=1 to=3 # sample values
# Ensure that $from and $to are decimal numbers and abort, if they are not.
(( 10#$from + 10#$to || 1 )) 2>/dev/null || { echo "Need decimal integers" >&2; exit 1; }
eval echo "A{$from..$to}" # -> 'A1 A2 A3'
Основной целью расширения является развернуть список токенов с каждым токеном, имеющим опциональный префикс и/или постфикс; разложение фигурных скобок должно быть неуказанным и прийти в 2 аромата:
echo A{b,c,d}
→ Ab Ac Ad
, т.е. 3 токена, что подразумевается количеством аргументов.echo {/,$HOME/}Library
например, → /Library /User/jdoe/Library
a выражение последовательности (диапазон) с ..
, обычно числовые - переменные НЕ поддерживаются
{a..c}
{1..10}
, {10..1}
, {-1..2}
A{1..3}#
→ A1# A2# A3#
{$from..$to} # !! FAILS
- $from
и $to
интерпретируются как литералы и поэтому не распознаются ни одной буквой, ни десятичным целым - не выполняется расширение брекетинга (см. ниже).
zsh
и ksh
.echo A{1..5..2}
→ A1 A3 A5
- числа, увеличивающиеся на 2echo A{001..003}
→ A001 A002 A003
недопустимое выражение не расширено (рассматривается как обычная строка без кавычек, с {
и }
рассматривается как литералы):
echo {}
→ '{}'
- недействителен в качестве фигурной скобки: не менее 2 ,
- необходимы разделенные токены
{}
с find
.echo {1..$to}
→ '{1..<value-of-$to>}'
- недействителен как выражение привязки. in bash
: переменные не поддерживаются; однако, действительны в ksh
и zsh
.fish
, напротив, расширяет последовательность {...}
, аналогично, zsh
имеет параметр BRACE_CCL
(по умолчанию отключен) для расширения отдельных символов внутри {..}
, что эффективно вызывает расширение любого непустого {...}
.)Проблема заключается в том, что "расширение скобки" выполняется перед "переменным расширением"
for i in $(seq 1 $howmany)
работает, как сказал @damienfrancois, или, если хотите:
for i in $(eval echo '{$start..10}')
возможно, но не использует его для всех здравомыслия.
Вы также можете использовать цикл while:
while ((howmany--)); do
echo "Welcome"
done
В этом случае мы могли бы использовать eval
:
howmany=`grep -c $1 /root/file`
for i in $(eval echo {1..$howmany}); do
echo "Welcome"
done