Який найкращий спосіб перевірити, чи є $ 1 цілим числом у / bin / dash?
У баші я міг би зробити:
[[ $1 =~ ^([0-9]+)$ ]]
Але це, здається, не сумісне з POSIX, і дефіс цього не підтримує
Який найкращий спосіб перевірити, чи є $ 1 цілим числом у / bin / dash?
У баші я міг би зробити:
[[ $1 =~ ^([0-9]+)$ ]]
Але це, здається, не сумісне з POSIX, і дефіс цього не підтримує
Відповіді:
Наступні виявляють цілі числа, додатні чи негативні, і працюють під 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; ну, цитата зі сторінки man, яку я дав, запропонувала щось інше, але я не можу покладатися на такі неофіційні заяви, я думаю. Стара оболонка Бурна все одно вже не така вже й значна, коли ми в епоху 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, оскільки поведінка не визначена, якщо операнди є десятковими цілими числами. Наприклад кенійських шилінгів, було б сказати , що 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
реалізації скажуть, що 999999999999999999999 не є цілим числом. POSIX не дає гарантії, що це буде працювати. На практиці принаймні в системі GNU буде сказано, що "length" - ціле число.
expr 9999999999999999999 + 0
надає мені 3 статусу виходу expr -12 + 0
та expr length + 0
дає мені статус 0 виходу з GNU expr ( + string
змушує string
розглядатися як рядок з GNU expr
. Працював expr "$a" - 0
би краще).
-12
, що це дійсне ціле число і 9999999999999999999
дало переповнення.
Ось проста функція, що використовує той самий метод, що і відповідь Муру :
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
не ціле число, але пройшло б цей тест.