




Переменные оболочки не имеют типа, поэтому самый простой способ - использовать команду типа возврата test:
if [ $var -eq $var 2> /dev/null ]; then ...
(Или еще раз проанализируйте его с помощью регулярного выражения)
Если var пуст, это дает ложное срабатывание. Может быть: if [ -n "$var" -a $var -eq $var 2> /dev/null ]; then echo is num; else echo not a num; fi
Также приятно, что это работает для базовых оболочек борна / корна (башизмы не нужны). Один недостаток: в тесте (1), который я использовал (FreeBSD 9, Fedora 20), это не удается, когда var чрезмерно инвертируется (например, --234), хотя арифметические операции работают (например, echo $((--234 * 2))).
if echo $var | egrep -q '^[0-9]+$'; then
# $var is a number
else
# $var is not a number
fi
Я не знаю, правильно ли это, это проверяет, что это целое число (а не число). Я бы изменил регулярное выражение на '[0-9]', чтобы решить проблему, если вопрос находится в описании ("содержит"), и изменить его для обработки нецелых чисел, если это вопрос в заголовке ("равно ").
Сколько тысяч циклов тратят вилка, труба и egrep на такую простую операцию, которую можно было бы выполнить в оболочке? Надеюсь, это не нужно в жестком цикле ...
@Jens: Вы правы, этот ответ не так эффективен, как ответ, который не порождает подпроцесс, хотя в большинстве случаев это не имеет никакого практического значения. Я поддержал ваш лучший ответ.
@AdamRosenfield Спасибо, это благородный жест перед лицом критики. Миру нужно больше такого отношения.
Не забывайте отрицательные числа. Предполагая, что мы говорим только о целых числах (целых числах), а не о числах с плавающей запятой (реальных), т.е. числах, которые работают с числовыми операторами test (1) (-eq и т. д.), Мы могли бы настроить здесь метод регулярных выражений. включить отрицательные целые числа, например: echo $var | egrep -q '^-*[[:digit:]]+$' && echo is num || echo not num (конечно, только для основания 10). Это работает даже с чрезмерно отрицательными, но допустимыми числами, такими как ---- 234.
В ksh93 или bash с включенной опцией extglob:
if [[ $var == +([0-9]) ]]; then ...
Чтобы обрабатывать отрицательные числа (даже чрезмерно, но законно отрицаемые, например --- 234), настройте это на if [[ $var == +(-*[[:digit:]]) ]]; then echo is num; else echo not num; fi. Приятно, что это обрабатывает пустой или неустановленный var, а также многословный var (например, «коричневая корова»). Используйте класс символов [:xdigit:] для чисел с основанием 16. Примечание: классы символов, не зависящие от локали (например, [: digit:]), похоже, не работают с ksh.
Это быстро усложняется. Попробуйте проверить с помощью «коричневая корова», «123Q», «0xAbc», «123 Q», «-123», «----- 345». А разнообразные реализации «расширенных регулярных выражений» в bash / ksh усложняют задачу. Голосовать против из-за отсутствия переносимости для основных оболочек posix (скорее против метода, чем за ответ Даррона, так как он был очень откровенен с этим ограничением).
вы можете помочь мне понять это: # x = 200 # [[+ ([0-9]) == $ x]] && номер эха || эхо не число> не число # [[$ x == + ([0-9])]] && эхо число || эхо не число> число
Это можно проверить с помощью регулярного выражения.
###
echo $var|egrep '^[0-9]+$'
if [ $? -eq 0 ]; then
echo "$var is a number"
else
echo "$var is not a number"
fi
Почему это было добавлено? Именно этот метод был в ответе Адама в 2008 году (-1).
Вот версия, использующая только функции, доступные в простой оболочке (т.е. она будет работать в sh), и с на один процесс меньше, чем при использовании grep:
if expr "$var" : '[0-9][0-9]*$'>/dev/null; then
echo yes
else
echo no
fi
Это проверяет, представляет ли $var целое число Только; настройте регулярное выражение по своему вкусу и обратите внимание, что аргумент регулярного выражения expr неявно привязан к началу.
Не поддерживает отрицательные целые числа (-123, --123).
Для отрицательных чисел: expr "$var" : '-*[0-9][0-9]*$' && echo num || echo not num
Проголосуйте за переносимость (например, отсутствие критики); небольшой недостаток для дополнительной вилки.
Ни вилок, ни труб. Чистая оболочка POSIX:
case $var in
(*[!0-9]*|'') echo not a number;;
(*) echo a number;;
esac
(Предполагается, что число: = строка цифр). Если вы хотите разрешить подписанные номера с одним ведущим - или +, удалите необязательный знак следующим образом:
case ${var#[-+]} in
(*[!0-9]*|'') echo not a number;;
(*) echo a number;;
esac
Не обрабатывает отрицательные числа (например, -123, --123).
@Juan: вот почему я прямо высказал это предположение.
Справедливо. Я просто подумал, что проясню все различные решения. На некоторых других довольно легко поддерживать отрицательные числа. Попытка поддержать отрицательные числа с помощью этого метода (обычная подстановка) сложнее.
@Juan Я добавил простую модификацию, разрешающую номера со знаком. Спасибо за вызов :-)
Хорошее дополнение. По-прежнему не работает для извращенных, но действительно --123. Интересно, что / bin / sh <10 (sh -c 'var=--123; echo $(($var))') справляется с этим. Но freebsd> = 10 не работает.
Оказалось, что --123 не работает в freebsd 10+ намеренно - чтобы явно указать, что оператор - не поддерживается. '- -123' и '- (- 123)' работают (но все еще проблематичны для вышеуказанного кода определения числа).
a=123
if [ `echo $a | tr -d [:digit:] | wc -w` -eq 0 ]
then
echo numeric
else
echo ng
fi
numeric
a=12s3
if [ `echo $a | tr -d [:digit:] | wc -w` -eq 0 ]
then
echo numeric
else
echo ng
fi
ng
Не могли бы вы пояснить свое решение?
@StevenWestbrook: это удаляет цифры из $ a и считает, что осталось. Если что-то осталось, то это не строка из одних цифр («не числовая»).
Не обрабатывает отрицательные числа (например, -123, --123). К сожалению, добавление поддержки отрицательных чисел с использованием этого тяжелого метода вилки означает добавление еще одного tr -d - в конвейер, я думаю.
Вы можете изменить выражение tr (1) на '[[: digit:] -]', чтобы поймать отрицательные числа (или использовать [: xdigit:] для чисел с основанием 16), но это даст ложное срабатывание с чем-то вроде 123-54. (думает, что это действительное число).
Я в некотором роде новичок в программировании оболочки, поэтому стараюсь найти самый простой и понятный Он просто проверит, что var больше или такое же, как 0 Я думаю, что это хороший способ выбора параметров ... может быть не то, что вообще ...:
if [ $var -ge 0 2>/dev/null ] ; then ...
если [$ var -ge 0 -o $ var -lt 0]; then ... # для обработки отрицательных чисел
if echo $var | egrep -q '^[0-9]+$'
На самом деле это не работает, если var многострочный.
т.е.
var = "123
qwer"
Особенно, если var исходит из файла:
var=`cat var.txt`
Это самый простой:
if [ "$var" -eq "$var" ] 2> /dev/null
then echo yes
else echo no
fi
Небольшой отрицательный голос за повторение ответа Петра 2008 года без указания авторства. Та же проблема с ложным срабатыванием, что и у этой (добавьте -n "$var", чтобы поймать пустую / неустановленную переменную). Смотрите комментарии там. Хороший аргумент в отношении потенциальных ложных срабатываний для многострочной проблемы.
Вы можете сделать это с помощью простой тестовой команды.
$ test ab -eq 1 >/dev/null 2>&1
$ echo $?
2
$ test 21 -eq 1 >/dev/null 2>&1
$ echo $?
1
$ test 1 -eq 1 >/dev/null 2>&1
$ echo $?
0
Таким образом, если статус выхода равен 0 или 1, тогда это целое число, но если статус exis равен 2, то это не число.
Downvote - по сути, то же самое, что и ответ @ Piotr 2008 года. Разве никто не просматривает существующие ответы перед тем, как ответить - особенно в той же теме (не говоря уже о других подобных темах)?
Вот тест без регулярных выражений (код tcsh):
Создайте файл с контрольным номером:
#! /usr/bin/env tcshif ( "$*" == "0" ) then
exit 0 # number
else
((echo "$*" | bc) > /tmp/tmp.txt) >& /dev/null
set tmp = `cat /tmp/tmp.txt`
rm -f /tmp/tmp/txt
if ( "$tmp" == "" || $tmp == 0 ) then
exit 1 # not a number
else
exit 0 # number
endif
endif
и беги
chmod +x checknumber
Использовать
checknumber -3.45
и вы получите результат как errorlevel ($?).
Вы можете легко его оптимизировать.
Вилка тяжелая. Существуют более легкие реализации для целых чисел (см. Предыдущие ответы), если все, что у вас есть, - это csh. Незначительный голос за обработку с плавающей запятой, хотя я предполагаю, что это не то, что хотел OP (OP был довольно расплывчатым в описании проблемы).
if echo "$var" | egrep -q '^\-?[0-9]+$'; then
echo "$var is an integer"
else
echo "$var is not an integer"
fi
тесты (с var = 2 и т. д.):
2 is an integer
-2 is an integer
2.5 is not an integer
2b is not an integer
if echo "$var" | egrep -q '^\-?[0-9]*\.?[0-9]+$'; then
echo "$var is a number"
else
echo "$var is not a number"
fi
тесты (с var = 2 и т. д.):
2 is a number
-2 is a number
-2.6 is a number
-2.c6 is not a number
2. is not a number
2.0 is a number
Конечно, .6 - это число. Команда также показывает это как число. Также 4. - это число, но эта команда сообщает, что это не число.
Принимая значение из командной строки и показывая ВХОД ДЕСЯТИЧНЫЙ / НЕ-ДЕСЯТИЧНЫЙ и ЧИСЛО или нет:
NUMBER=$1
IsDecimal=`echo "$NUMBER" | grep "\."`
if [ -n "$IsDecimal" ]
then
echo "$NUMBER is Decimal"
var1=`echo "$NUMBER" | cut -d"." -f1`
var2=`echo "$NUMBER" | cut -d"." -f2`
Digit1=`echo "$var1" | egrep '^-[0-9]+$'`
Digit2=`echo "$var1" | egrep '^[0-9]+$'`
Digit3=`echo "$var2" | egrep '^[0-9]+$'`
if [ -n "$Digit1" ] && [ -n "$Digit3" ]
then
echo "$NUMBER is a number"
elif [ -n "$Digit2" ] && [ -n "$Digit3" ]
then
echo "$NUMBER is a number"
else
echo "$NUMBER is not a number"
fi
else
echo "$NUMBER is not Decimal"
Digit1=`echo "$NUMBER" | egrep '^-[0-9]+$'`
Digit2=`echo "$NUMBER" | egrep '^[0-9]+$'`
if [ -n "$Digit1" ] || [ -n "$Digit2" ]; then
echo "$NUMBER is a number"
else
echo "$NUMBER is not a number"
fi
fi
( test ! -z "$num" && test "$num" -eq "$num" 2> /dev/null ) && {
# $num is a number
}
Это приведет к сбою непривлекательным образом из-за отсутствие цитирования для любого нетривиального строкового ввода.
@tripleee исправлено
Но действительно ли необходима проверка -z? test "" -eq "" 2>/dev/null делает то, что я ожидаю здесь (старый Bash 3.2 на стандартной macOS). Тем не менее, круглые скобки кажутся излишними (и стоят вам ненужной подоболочки).
Заголовок спрашивает, является ли переменная числом, а описание спрашивает, содержит ли она число. Какой ты хочешь? Кроме того, когда вы говорите число d o, вы имеете в виду целое число или оно должно обрабатывать десятичные дроби?