2015-02-25 3 views
1
#!/bin/bash 

echo "Enter number of loops" 
read count 
echo $count 
if [ $count -eq 0 ] 
then 
    echo "The count cannot be zero. Enter a number again" 
    read count 
fi 

while [ $count -gt 0 ] 
do 
    echo "Loop numner $count" 
    count = `expr $count - 1` 
done 

Я пытаюсь имитировать счетчик Java в bash. Это существует?Почему эта программа bash переходит в бесконечный цикл?

+1

Являются ли 'for ((count = n; count> 0; --count)); делать ...; done' или 'count = $ n; while ((count--)); делать ... ; done' что вы ищете? – rici

ответ

5

У вас есть пространство между вашим оператором присваивания, как показано ниже:

count = `expr $count - 1` 
    ^^ 

Удалить пространство между «=», как показано ниже:

count=`expr $count - 1` 
Output 
Enter number of loops 
10 
10 
Loop numner 10 
Loop numner 9 
Loop numner 8 
Loop numner 7 
Loop numner 6 
Loop numner 5 
Loop numner 4 
Loop numner 3 
Loop numner 2 
Loop numner 1 

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

count=$(expr $count - 1) 
+0

спасибо. Есть ли какая-то особая причина, по которой отступники не поощряются? – Ralph

+0

@ Ralphyabro: они не могут быть вложены без головной боли. 'echo $ (echo $ (echo hello))' отлично ... как вы это делаете с backticks? –

+0

Спасибо gniourf_gniourf, @Ralphyabro, что вы даже можете обратиться к [wiki] (http://mywiki.wooledge.org/BashFAQ/082) – SMA

0

Вы также можете использовать арифметическое расширение bash:

count="$((count -1))" 

Я хотел бы также предложить сделать первый тест -le не -EQ, в случае, если пользователь вводит в отрицательное число, а не цитировать его в случае пользователь печатает ничего.

if [ "$count" -le 0 ] 

Так что ваш код будет:

#!/bin/bash 

    echo "Enter number of loops" 
    read count 
    echo $count 
    if [ "$count" -le 0 ] 
    then 
     echo "The count cannot be zero. Enter a number again" 
     read count 
    fi 

    while [ $count -gt 0 ] 
    do 
     echo "Loop numner $count" 
     count="$((count - 1))" 
    done 
3

Вот скала переписывание вашего сценария, чтобы показать вам, как это обычно делается:

#!/bin/bash 

while true; do 
    read -rep "Enter number of loops: " count 
    if [[ $count = +([[:digit:]]) ]]; then 
     ((count=10#$count)) 
     ((count>0)) && break 
     printf 'The count cannot be zero. Enter a number again.\n' 
    else 
     printf 'Please enter a valid number.\n' 
    fi 
done 

while ((count>0)); do 
    printf 'Loop number %s\n' "$count" 
    ((--count)) 
done 
  • Использование read с -r Флаг, чтобы иметь обратную косую черту, не избежать некоторых символов (это должно быть значение по умолчанию), с -e, так что read использует readline: он более удобен для пользователя, а с опцией -p указать подсказку.
  • Я полностью перепробовал логику, которую вы используете, чтобы читать ввод пользователя: read запускается в бесконечном цикле, который может быть разорван только тогда, когда пользователь вводит действительное число. С помощью вашего метода пользователь может ввести неверные данные дважды, и цикл будет работать со случайными аргументами. Нехорошо.
  • Чтобы проверить, что пользовательский ввод действителен, я использую сопоставление с образцом: [[ $count = +([[:digit:]]) ]], который является истинным тогда и только тогда, когда count расширяется до строки из одной или нескольких цифр, тогда я уверен, что Bash будет обрабатывать count в radix 10: в арифметическом контексте 10#$count обрабатывает счет в радиусе 10. Без этого входной сигнал, такой как 08 или 09, заставит некоторые последующие части сработать, как ведущее значение нуля, для Bash, чтобы число было интерпретировано в radix 8, следовательно 08 не действует!
  • Заключительный цикл написан с использованием арифметического контекста Баша ((...)). Для выполнения простой арифметики вам не нужен внешний expr.
Смежные вопросы