Как лучше всего проверить, является ли $ 1 целым числом в / bin / dash?
В bash я мог бы сделать:
[[ $1 =~ ^([0-9]+)$ ]]
Но это не похоже на POSIX-совместимость и Dash не поддерживает это
Как лучше всего проверить, является ли $ 1 целым числом в / bin / dash?
В bash я мог бы сделать:
[[ $1 =~ ^([0-9]+)$ ]]
Но это не похоже на POSIX-совместимость и Dash не поддерживает это
Ответы:
Следующее определяет целые числа, положительные или отрицательные, и работает в dash
POSIX:
echo "$1" | grep -Eq '^[+-]?[0-9]+$' && echo "It's an integer"
case "${1#[+-]}" in
''|*[!0-9]*)
echo "Not an integer" ;;
*)
echo "Integer" ;;
esac
Или с небольшим использованием команды :
(nop):
! case ${1#[+-]} in *[!0-9]*) :;; ?*) ! :;; esac && echo Integer
Независимо от того dash
, bash
, ksh
, zsh
, POSIX sh
, или posh
( "переопределение Борна оболочки" sh
); case
конструкция является наиболее доступной и надежной:
case $1 in (*[!0-9]*|"") false ;; (*) true ;; esac
dash
? Это работает для меня под, bash
но не dash
.
dash
; чтобы опросить результат я добавил echo $?
после команды case.
posh
(«переопределение оболочки Борна») также не имеет проблем с этим решением.
case
; Одна из причин - это ошибка, которую вы описываете, другая - в редакторах, которые имеют функции, основанные на сопоставлении скобок (vim), они дают гораздо лучшую поддержку, и, что не менее важно, я считаю, что лично лучше, чтобы они соответствовали. - WRT posh
- это POSIX; ну, цитата из справочной страницы, которую я дал, предложила кое-что еще, но я не могу полагаться на такие неофициальные заявления в любом случае. Старая оболочка Bourne уже не так важна, как сейчас, в эпоху POSIX.
Вы можете использовать -eq
тест для строки с самим собой:
$ dash -c 'a="a"; if [ "$a" -eq "$a" ] ; then echo number; else echo not a number; fi'
dash: 1: [: Illegal number: a
not a number
$ dash -c 'a="0xa"; if [ "$a" -eq "$a" ] ; then echo number; else echo not a number; fi'
dash: 1: [: Illegal number: 0xa
not a number
$ dash -c 'a="-1"; if [ "$a" -eq "$a" ] ; then echo number; else echo not a number; fi'
number
Если сообщение об ошибке является проблемой, перенаправьте вывод ошибки на /dev/null
:
$ dash -c 'a="0xa"; [ "$a" -eq "$a" ] 2>/dev/null|| echo no'
no
" 023 "
это число. Обратите внимание, что он работает с дефисом, но не со всеми другими оболочками POSIX, так как поведение не определено, если операнды представляют собой целые числа после запятой. Например, с помощью ksh можно сказать, что SHLVL
или 1+1
это число.
Попробуйте использовать его как арифметическое расширение и посмотрите, работает ли оно. На самом деле, вам нужно быть немного строже, чем это, потому что арифметические расширения будут игнорировать, например, начальные и конечные пробелы. Сделайте арифметическое расширение и убедитесь, что расширенный результат точно соответствует исходной переменной.
check_if_number()
{
if [ "$1" = "$((${1}))" ] 2>/dev/null; then
echo "Number!"
else
echo "not a number"
fi
}
Это также будет принимать отрицательные числа - если вы действительно хотите исключить их, добавьте дополнительную проверку для $((${1} >= 0))
.
[[
$(( ... ))
? Если это так, мой ответ все еще должен быть материально правильным, мне просто нужно добавить дополнительные цитаты.
check_if_number 1.2
и функция вернулась: dash: 3: arithmetic expression: expecting EOF: "1.2"
Возможно с expr
?
if expr match "$1" '^\([0-9]\+\)$' > /dev/null; then
echo "integer"
else
echo "non-integer"
fi
match
ни \+
Было бы также сказать, 0 не число. Вы хотитеexpr "x$1" : 'x[0-9]\{1,\}$'
В системе POSIX вы можете использовать expr :
$ a=a
$ expr "$a" - 0 >/dev/null 2>&1
$ [ "$?" -lt 2 ] && echo Integer || echo Not Integer
expr
реализации скажут, что 9999999999999999999 не является целым числом. POSIX не дает никаких гарантий, что это будет работать. На практике, по крайней мере, в системе GNU будет сказано, что «длина» - это целое число.
expr 9999999999999999999 + 0
дает мне статус на 3 выхода и expr -12 + 0
и expr length + 0
дать мне статус в 0 выездном с GNU выража ( + string
силами , string
которые будут рассматриваться как строка с GNU expr
. expr "$a" - 0
Будет работать лучше).
-12
является допустимым целым числом и 9999999999999999999
дал переполнение.
Вот простая функция, использующая тот же метод, что и ответ muru :
IsInteger() # usage: IsInteger string
{ # returns: flag
[ "$1" -eq "$1" ] 2> /dev/null
}
Пример:
p= n=2a3; IsInteger $n || p="n't" ; printf "'%s' is%s an integer\n" "$n" "$p"
p= n=23; IsInteger $n || p="n't" ; printf "'%s' is%s an integer\n" "$n" "$p"
Выход:
'2a3' isn't an integer
'23' is an integer
foo\n123\nbar
не целое число, но пройдет этот тест.