Как проверить, является ли переменная числом в Bash? - PullRequest
513 голосов
/ 30 апреля 2009

Я просто не могу понять, как убедиться, что аргумент, переданный моему сценарию, является числом или нет.

Все, что я хочу сделать, это что-то вроде этого:

test *isnumber* $1 && VAR=$1 || echo "need a number"

Любая помощь?

Ответы [ 38 ]

0 голосов
/ 17 октября 2010

Я попробовал рецепт ультразвука, поскольку он показался мне наиболее практичным, и не смог заставить его работать. В конце концов я разработал другой способ, основанный, как и другие, на подстановке параметров, на этот раз с заменой регулярного выражения:

[[ "${var//*([[:digit:]])}" ]]; && echo "$var is not numeric" || echo "$var is numeric"

Он удаляет каждый символ: digit: class в $ var и проверяет, остались ли у нас пустые строки, что означает, что в оригинале были только цифры.

Что мне нравится в этом, так это его компактность и гибкость. В этой форме он работает только для целых 10 без разделителей, хотя, безусловно, вы можете использовать сопоставление с образцом для соответствия другим потребностям.

0 голосов
/ 26 марта 2014

Принятый ответ здесь не работает, я на MacOS. Работает следующий код:

if [ $(echo "$number" | grep -c '^[0-9]\+$') = 0 ]; then 
    echo "it is a number"
else
    echo "not a number"
fi
0 голосов
/ 24 декабря 2010

Quick & Dirty: я знаю, что это не самый элегантный способ, но я обычно просто добавляю к нему ноль и проверяю результат. вот так:

function isInteger {
  [ $(($1+0)) != 0 ] && echo "$1 is a number" || echo "$1 is not a number"
 }

x=1;      isInteger $x
x="1";    isInteger $x
x="joe";  isInteger $x
x=0x16 ;  isInteger $x
x=-32674; isInteger $x   

$ (($ 1 + 0)) вернет 0 или бомбу, если $ 1 НЕ является целым числом. Например:

function zipIt  { # quick zip - unless the 1st parameter is a number
  ERROR="not a valid number. " 
  if [ $(($1+0)) != 0 ] ; then  # isInteger($1) 
      echo " backing up files changed in the last $1 days."
      OUT="zipIt-$1-day.tgz" 
      find . -mtime -$1 -type f -print0 | xargs -0 tar cvzf $OUT 
      return 1
  fi
    showError $ERROR
}

ПРИМЕЧАНИЕ: я думаю, я никогда не думал проверять поплавки или смешанные типы, которые сделают всю скриптовую бомбу ... в моем случае я не хотел, чтобы это продолжалось. Я собираюсь поиграть с решением mrucci и регулярным выражением Даффи - они кажутся наиболее надежными в рамках bash ...

0 голосов
/ 27 октября 2013

Вы можете использовать «let» тоже так:

[ ~]$ var=1
[ ~]$ let $var && echo "It's a number" || echo "It's not a number"
It\'s a number
[ ~]$ var=01
[ ~]$ let $var && echo "It's a number" || echo "It's not a number"
It\'s a number
[ ~]$ var=toto
[ ~]$ let $var && echo "It's a number" || echo "It's not a number"
It\'s not a number
[ ~]$ 

Но я предпочитаю использовать оператор "= ~" Bash 3+, как некоторые ответы в этой теме.

0 голосов
/ 09 января 2019

Если у вас установлен Perl, этот вкладыш прост, читабелен и расширяем

perl -se 'exit($n !~ /\d+/)' -- -n=a

Вот несколько тестов

perl -se 'exit($n !~ /\d+/)' -- -n=a; echo $?
1
perl -se 'exit($n !~ /\d+/)' -- -n=2; echo $?
0

Это довольно понятно, но вот больше информации

  • -e включает оценку
  • -s разрешает передачу аргументов после - в этом случае -n
  • !~ является оператором совпадения регулярного выражения отрицания, поскольку 0 в bash - это успех, мы хотим, чтобы он успешно завершился, если аргумент -n - это число

Вы захотите обернуть это в функцию, здесь лучшая версия, которая также может читать числа с плавающей точкой

is_number() { perl -se 'exit($n !~ /^\d+(\.\d+)?$/)' -- -n="$1"; }
0 голосов
/ 04 мая 2009

Я использую следующее (для целых чисел):

## ##### constants
##
## __TRUE - true (0)
## __FALSE - false (1)
##
typeset -r __TRUE=0
typeset -r __FALSE=1

## --------------------------------------
## isNumber
## check if a value is an integer 
## usage: isNumber testValue 
## returns: ${__TRUE} - testValue is a number else not
##
function isNumber {
  typeset TESTVAR="$(echo "$1" | sed 's/[0-9]*//g' )"
  [ "${TESTVAR}"x = ""x ] && return ${__TRUE} || return ${__FALSE}
}

isNumber $1 
if [ $? -eq ${__TRUE} ] ; then
  print "is a number"
fi
0 голосов
/ 02 июня 2019

Принятый ответ не работал для меня во всех случаях BASH 4+, поэтому:

# -- is var an integer? --
# trim leading/trailing whitespace, then check for digits return 0 or 1
# Globals: None
# Arguments: string
# Returns: boolean
# --
is_int() {
    str="$(echo -e "${1}" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')"
    case ${str} in ''|*[!0-9]*) return 1 ;; esac
    return 0
}

Как это использовать?

Действительный (вернет 0 = true):

is_int "100" && echo "return 0" || echo "return 1"

Неверно (вернет 1 = ложь):

is_int "100abc" && echo "returned 0" || echo "returned 1"
is_int ""  && echo "returned 0" || echo "returned 1"
is_int "100 100"  && echo "returned 0" || echo "returned 1"
is_int "      "  && echo "returned 0" || echo "returned 1"
is_int $NOT_SET_VAR  && echo "returned 0" || echo "returned 1"
is_int "3.14"   && echo "returned 0" || echo "returned 1"

Выход:

returned 0
returned 1
returned 1
returned 1
returned 1
returned 1
returned 1

примечание, в Bash, 1 = false, 0 = true. Я просто распечатываю это, где вместо этого было бы что-то подобное:

if is_int ${total} ; then
    # perform some action 
fi
0 голосов
/ 14 августа 2012
  • переменная для проверки

    number=12345 или number=-23234 или number=23.167 или number=-345.234

  • проверка числовых или не числовых

    echo $number | grep -E '^-?[0-9]*\.?[0-9]*$' > /dev/null

  • принять решение о дальнейших действиях в зависимости от состояния выхода из вышеуказанного

    if [ $? -eq 0 ]; then echo "Numeric"; else echo "Non-Numeric"; fi

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...