Просто используйте:
#! /bin/bash -
n=
pattern='^(0+|[123456789][0123456789]*)$' # decimal integer number,
# exclude 0123 octals
until [[ $n =~ $pattern ]]; do
IFS= read -rp 'Enter a decimal number: ' n || exit # exit upon EOF
done
или:
#! /bin/bash -
pattern='^(0+|[123456789][0123456789]*)$' # decimal integer number,
# exclude 0123 octals
while true; do
IFS= read -rp 'Enter a decimal number: ' n || exit # exit upon EOF
if [ -z "$n" ]; then
echo >&2 "Cannot be empty, try again"
elif [[ ! $n =~ $pattern ]]; then
echo >&2 "Not a decimal integer number, try again"
else
break
fi
done
Или, лучше, используйте стандартный синтаксис sh
, и тогда вам даже не понадобитсяbash
:
#! /bin/sh -
while true; do
printf >&2 'Enter a number: '
IFS= read -r n || exit # exit upon EOF
case $n in
("")
echo >&2 "Cannot be empty, try again";;
(*[!0123456789]* | 0*[!0]*)
echo >&2 "Not a decimal integer number, try again";;
(*)
break;; # OK
esac
done
Обратите внимание, что [
является встроенной оболочкой. [
из bash
, в отличие от zsh
или yash
, не поддерживает оператор =~
.
Кроме того, если вы сделаете [ x && y ]
, это будет проанализировано как cmd1 arg && cmd2 arg2
, поэтому просто запустите [ x
и, если это успешно, запустите y ]
.
[[... ]]
, с другой стороны, является специальной конструкцией оболочки (из ksh ), внутри которой &&
также является формой операторов и .
Однако, если написать:
[[ -z $var && $var =~ ^[0-9]+$ ]]
Это проверка того, является ли $var
пустым(-z
)и соответствует ли ^[0-9]+$
, что невозможно.
Думаю, вы имели в виду:
[[ -z $var || ! $var =~ ^[0-9]+$ ]]
Но даже в этом случае -z $var
является избыточным, поскольку, если $var
соответствует^[0-9]+$
(одному или нескольким символам в диапазоне 0 -9 ), он не может быть пустым.
Обратите внимание, что совпадение [0-9]
является более или менее случайным в большинстве локалей и большинства систем, используйте [0123456789]
, если вы хотите сопоставить любые десятичные цифры.
В оболочках, подобных bash
, рекомендуется исключать числа с ведущими нулями, поскольку они, как правило, интерпретируются как восьмеричные числа (, где 010 означает, например, 8 ).
Принято выдавать пользовательские подсказки на stderr (подобно bash
's read -p
), поскольку они не являются частью обычного вывода команды (вывода, который производит ваш скрипт , если таковые имеются, и которые вы можете, например, захотеть передать какой-либо другой команде ).