#linux #bash #shell #decimal #posix
#linux #bash #оболочка #десятичные #posix
Вопрос:
Я пишу небольшой скрипт, чтобы легко фиксировать веса, которые берутся из пользовательского ввода с помощью read -p
.
Я хочу, чтобы все записанные веса были длиной в 4 символа, десятичные числа в формате XX.X. Например, 30,2 кг.
#!/bin/bash
# take input from prompt (-p) and store it in $varweight
read -p 'Enter weight in kg: ' varweight
Как я могу убедиться, что пользователи могут вводить десятичные числа только в этом формате?
Спасибо за вашу помощь.
Комментарии:
1. А если вес < 10?
Ответ №1:
Одним из способов было бы использовать регулярное выражение и указывать длину для удаления ложных срабатываний (необязательно). Конечно, для приведенного ниже потребуется bash
оболочка, потому что ~
не соответствует POSIX
str="30.4"
re='^[[:digit:]]{2}.[[:digit:]]$'
if [[ $str =~ $re ]]; then
echo 'true'
fi
Хотя в оболочке, совместимой с POSIX, вы могли бы использовать case
оператор
case $str in
[0-9][0-9].[0-9]) echo good ;;
*) echo bad;;
esac
Гораздо лучшим инструментом, совместимым с POSIX, было бы использовать expr
для сопоставления регулярных выражений.
if expr "$str" : '[[:digit:]]{2}.[[:digit:]]$' > /dev/null; then
echo "true"
fi
Комментарии:
1. Используйте
expr
для проверкиstr
, а не разбивайте его пополам и проверяйте длину каждого компонента (что не отсеивает недопустимые входные данные, такие какxy.z
).if expr "$str" : '[[:digit:]]{2}.[[:digit:]]$' > /dev/null; then
.2. @chepner: Совместимо ли условие if с
((..))
POSIX тоже? Я думаю, что да3. Нет. В POSIX есть арифметические выражения (
$((...))
), но нет арифметической составной команды (((...))
).4.
case
Оператор в порядке; кроме того,.
не обязательно использовать escape, поскольку он не имеет особого значения в шаблоне.