Используя ввод данных пользователем для определения, сколько раз для цикла выполняет итерации

Я испытываю затруднения при получении, чтобы цикл взял ввод данных пользователем в форме аргумента функции, которую я создал.

#!/bin/bash
number1="$1"    #Assume user input 5
loops="$2"      #Assume user input 5
if [[ ${number1} && ${loops} =~ ^-?[0.00-9.99]+$ ]];then
   for number2 in {1..${loops}}
   do
       Product=$(echo "${number1} * ${number2}" | bc -l)
       echo "${number1} * ${number2} = ${Product}"
       if test ${number2} -eq 7;then
           { echo "----------------------"; echo "${number2} is the best number."; echo "----------------------"; continue; }
       elif test ${number2} -eq 11;then
           { echo "------------------------------"; echo "${number2} is pretty awesome as well."; echo "------------------------------"; continue; }    
       fi 
   done
else
   { echo "Please try again with a valid numerical entry."; exit 1; }
fi

Этот сценарий не работает когда вводы данных пользователем целое число для переменных "циклов" и любое число для "number1". number1 = 5 в этом случае. Это возвращает ошибку:

(standard_in) 1: синтаксическая ошибка

5 * {1.. 5} =

/home/$USER/For_Loop_Multiplication.sh: строка 9: тест: {1.. 5}: целое выражение ожидается

/home/$USER/For_Loop_Multiplication.sh: строка 11: тест: {1.. 5}: целое выражение ожидается

Если я вместо этого непосредственно ввел конец, привязал количество циклов непосредственно в сценарий как следующее и number1 = 5, это хорошо работает:

#!/bin/bash
number1="$1"     #Assume user input 5
if [[ ${number1} =~ ^-?[0.00-9.99]+$ ]];then
   for number2 in {1..5}
   do
       Product=$(echo "${number1} * ${number2}" | bc -l)
       echo "${number1} * ${number2} = ${Product}"
       if test ${number2} -eq 7;then
           { echo "----------------------"; echo "${number2} is the best number."; echo "----------------------"; continue; }
       elif test ${number2} -eq 11;then
           { echo "------------------------------"; echo "${number2} is pretty awesome as well."; echo "------------------------------"; continue; }    
       fi 
   done
else
   { echo "Please try again with a valid numerical entry."; exit 1; }
fi

Это возвращает результат:

5 * 1 = 5

5 * 2 = 10

5 * 3 = 15

5 * 4 = 20

5 * 5 = 25

По существу то, что я думаю, происходит, то, что сценарий, кажется, помещает весь диапазон как значение number2, который определяется как итератор в для цикла. Так как вход для переменных "циклов" является целым числом, не должно быть никакого различия между выяснением у пользователя для диапазона и размещением его в цикле или просто установке его как значение по умолчанию, когда я пишу сценарий. Однако, по-видимому, существует различие... Любое понимание решения этой проблемы ценится.Спасибо.

2
задан 24 December 2015 в 11:54

1 ответ

Проблемой является эта строка:

for number2 in {1..${loops}}

Это - вопрос приоритета. Как объяснено в man bash:

порядок расширений: расширение фигурной скобки; расширение тильды, параметр и переменное расширение, арифметическое расширение и замена команды (выполненный слева направо вид); разделение слова; и расширение пути.

Так, расширение фигурной скобки происходит прежде переменное расширение. Поэтому, когда фигурные скобки расширены, $loops не был оценен к 5. Это означает, что {1..$loops} (Вам не нужно второе {}) расширяется до строки {1..5} а не последовательность чисел от 1 до 5. То же самое происходит при использовании строки вместо переменной:

$ echo {1..5}  ## works: prints a sequence
1 2 3 4 5
$ echo {1..foo} ## fails: prints a string with no expansion
{1..foo}

Как обходное решение, можно использовать seq:

for number2 in $(seq 1 "$loops"); do ...

Или, еще лучше, правильный цикл для задания:

for((number2=0;number2<=$loops; number2++)); do ...


Примечание: Как правило, необходимо также всегда заключать переменные в кавычки.

5
ответ дан 2 December 2019 в 01:58

Другие вопросы по тегам:

Похожие вопросы: