
Недавно я пытался создать скрипт, который может преобразовывать двоичное число в десятичное. Вот что у меня получилось:
#!/bin/bash
echo "Specify no of digits"
read digits
if [[ $digits == 1 ]]; then
echo "Enter 1 st digit"
read 1
elif [[ $digits == 2 ]]; then
echo "Enter 1 st digit"
read 1
echo "Enter 2 nd digit"
read 2
elif [[ $digits == 3 ]]; then
echo "Enter 1 st digit"
read 1
echo "Enter 2 nd digit"
read 2
echo "Enter 3 rd digit"
read 3
elif [[ $digits > 3 ]]; then
echo "Enter 1 st digit"
read 1
echo "Enter 2 nd digit"
read 2
echo "Enter 3 rd digit"
read 3
for digitno in {4..$digits};
do
echo "Enter $digitno th digit"
read $digitno
($nodigits++)
done
echo "$4"
else
echo "Please enter a valid no of digits. Type './binary_decoder.sh'"
exit 1
fi
Я знаю, что это довольно длинный сценарий. Но, пожалуйста, постарайтесь уделить время изучению этого сценария.
Если вы посмотрите на любую из read
строк внутри условного оператора if, вы увидите, что переменные, которым read
операторы присваивают числа, сами являются числами. С синтаксисом Bash это не сработает. Я хочу, чтобы переменные были такими, как n1, n2, n3, n4... и так далее. Но если вы посмотрите внутрь оператора elif [[ $digits > 3 ]]; then
, вы увидите, что есть цикл for, который позволяет декодировать бесконечное количество цифр. Теперь я не знаю способа добавить строку n
к числу в переменной $digitno
. Но мне было интересно, может ли кто-нибудь из вас разобраться, как добавить строку n
к $digitno
переменной.
Любая помощь будет оценена по достоинству.
решение1
Вы можете добавить строку к числу, используя простую конкатенацию:
$ i=3
$ echo n$i
n3
Однако это не очень помогает в достижении вашей настоящей цели, которая, по-видимому, заключается в том,как назначить неопределенное количество пользовательских вводов индексированным переменным.
Как вы уже обнаружили, в команде нельзя использовать переменные с именами , 1
и т. д . Помимо того, что имена переменных bash должны быть как минимум2
3
read
начинатьс буквенным символом или подчеркиванием, расширения $1
, $2
, $3
и т. д. зарезервированы для оболочкипозиционные параметры.
Если вы действительно хотите использовать $1
... $n
в своем скрипте, вы можете сделать это с помощью set
встроенной оболочки. Обратите внимание, что в то время как POSIX требует поддержки только параметров до $9
, bash поддерживает произвольное число (хотя для индексов выше 9 вам нужно будет использовать фигурные скобки, чтобы устранить неоднозначность между, например, ${10}
как 10 -й позиционный параметр и $10
как конкатенация $1
с литералом 0
). Например:
#!/bin/bash
set --
while : ; do
read -n1
case $REPLY in
[01]) set -- "$@" "$REPLY"
;;
*) break
;;
esac
done
for ((i=1; i<=$#; ++i)); do
printf 'Digit #%d = %d\n' "$i" "${!i}"
done
Пользователь вводит последовательность 0
символов 1
и завершает последовательность нажатием любого другого символа (включая символ новой строки):
$ ./bin2dec
1011010110
Digit #1 = 1
Digit #2 = 0
Digit #3 = 1
Digit #4 = 1
Digit #5 = 0
Digit #6 = 1
Digit #7 = 0
Digit #8 = 1
Digit #9 = 1
Digit #10 = 0
В качестве альтернативы вы можете сделать по сути то же самое с помощью пользовательского массива:
#!/bin/bash
arr=()
while : ; do
read -n1
case $REPLY in
[01]) arr+=("$REPLY")
;;
*) break
;;
esac
done
for ((i=0; i<${#arr[@]}; ++i)); do
printf 'Digit #%d = %d\n' "$i" "${arr[i]}"
done
Обратите внимание на различную индексацию: хотя оба массива начинаются с нуля, нулевой элемент $@
зарезервирован для имени файла скрипта.