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

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

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

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

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

Ответы [ 38 ]

1 голос
/ 04 апреля 2019

Для моей проблемы мне нужно было только убедиться, что пользователь случайно не введет какой-то текст, поэтому я старался сделать его простым и читабельным

isNumber() {
    (( $1 )) 2>/dev/null
}

Согласно справочной странице, это в значительной степени делает то, что я хочу

Если значение выражения не равно нулю, возвращаемый статус - 0

Для предотвращения появления неприятных сообщений об ошибках для строк, которые «могут быть числами», я игнорирую вывод ошибки

$ (( 2s ))
bash: ((: 2s: value too great for base (error token is "2s")
1 голос
/ 30 сентября 2015

Мне нравится ответ Альберто Закканьи.

if [ "$var" -eq "$var" ] 2>/dev/null; then

Важные предпосылки: - не появилось подоболочек - парсеры RE не вызваны - большинство приложений оболочки не используют действительные числа

Но если $var является сложным (например, доступ к ассоциативному массиву), и если число будет неотрицательным целым числом (в большинстве случаев), то это, возможно, более эффективно?

if [ "$var" -ge 0 ] 2> /dev/null; then ..
1 голос
/ 04 марта 2013

Чтобы поймать отрицательные числа:

if [[ $1 == ?(-)+([0-9.]) ]]
    then
    echo number
else
    echo not a number
fi
0 голосов
/ 09 марта 2015

Я использую printf в качестве других упомянутых ответов, если вы предоставите строку формата "% f" или "% i", printf выполнит проверку за вас. Синтаксис проще, чем изобретать чеки, и он короток, а printf вездесущ. Так что, на мой взгляд, это достойный выбор - вы также можете использовать следующую идею для проверки ряда вещей, она полезна не только для проверки чисел.

declare  -r CHECK_FLOAT="%f"  
declare  -r CHECK_INTEGER="%i"  

 ## <arg 1> Number - Number to check  
 ## <arg 2> String - Number type to check  
 ## <arg 3> String - Error message  
function check_number() { 
  local NUMBER="${1}" 
  local NUMBER_TYPE="${2}" 
  local ERROR_MESG="${3}"
  local -i PASS=1 
  local -i FAIL=0   
  case "${NUMBER_TYPE}" in 
    "${CHECK_FLOAT}") 
        if ((! $(printf "${CHECK_FLOAT}" "${NUMBER}" &>/dev/random;echo $?))); then 
           echo "${PASS}"
        else 
           echo "${ERROR_MESG}" 1>&2
           echo "${FAIL}"
        fi 
        ;;                 
    "${CHECK_INTEGER}") 
        if ((! $(printf "${CHECK_INTEGER}" "${NUMBER}" &>/dev/random;echo $?))); then 
           echo "${PASS}"
        else 
           echo "${ERROR_MESG}" 1>&2
           echo "${FAIL}"
        fi 
        ;;                 
                     *) 
        echo "Invalid number type format: ${NUMBER_TYPE} to check_number()." 1>&2
        echo "${FAIL}"
        ;;                 
   esac
} 

>$ var=45

>$ (($(check_number $var "${CHECK_INTEGER}" "Error: Found $var - An integer is required."))) && { echo "$var+5" | bc; }

0 голосов
/ 25 сентября 2016

Стек выскакивает сообщение, спрашивающее меня, действительно ли я хочу ответить после 30+ ответов? Но конечно!!! Используйте новые функции bash, и вот оно: (после комментария я внес изменение)

function isInt () {([[$ 1 -eq $ (($ 1 + 0))]] 2> / dev / null && [[$ 1! = '']] && echo 1) || echo ''}

function isInt() {
   ([[ $1 =~ ^[-+0-9]+$  ]] && [[ $1 -eq $(( $1 + 0 )) ]] 2>/dev/null && [[ $1 != '' ]] && echo 1) || echo ''
}

Поддержка:

===============out-of-the-box==================
 1. negative integers (true & arithmetic),
 2. positive integers (true & arithmetic),
 3. with quotation (true & arithmetic),
 4. without quotation (true & arithmetic),
 5. all of the above with mixed signs(!!!) (true & arithmetic),
 6. empty string (false & arithmetic),
 7. no value (false & arithmetic),
 8. alphanumeric (false & no arithmetic),
 9. mixed only signs (false & no arithmetic),
================problematic====================
 10. positive/negative floats with 1 decimal (true & NO arithmetic),
 11. positive/negative floats with 2 or more decimals (FALSE & NO arithmetic).

True / false - это то, что вы получаете от функции только при использовании в сочетании с подстановкой процесса, как в [[ $( isInt <arg> ) ]], так как в bash нет логического типа и не return значение функции.

Я использую заглавные буквы, когда результат тестового выражения НЕПРАВИЛЬЕН, тогда как он должен быть обратным!

Под «арифметикой» я имею в виду bash может выполнять математические операции, как в следующем выражении: $x=$(( $y + 34)).

Я использую «арифметику / отсутствие арифметики», когда в математических выражениях аргумент действует так, как ожидается, и «НЕТ арифметики», когда он ведет себя не так, как ожидалось.

Как видите, только 10 и 11 не являются проблемными!

Отлично!

PS: Обратите внимание, что MOST популярный ответ не удается в случае 9!

0 голосов
/ 13 февраля 2012

Я нашел довольно короткую версию:

function isnum()
{
    return `echo "$1" | awk -F"\n" '{print ($0 != $0+0)}'`
}
0 голосов
/ 26 апреля 2016

В ответ на ответ Дэвида W с октября 2013 г., если использовать expr, это может быть лучше

test_var=`expr $am_i_numeric \* 0` >/dev/null 2>&1
if [ "$test_var" = "" ]
then
    ......

Если числовое значение, умноженное на 1, дает одинаковое значение (включая отрицательные числа). В противном случае вы получите null, который вы можете проверить на

0 голосов
/ 06 января 2016
printf '%b' "-123\nABC" | tr '[:space:]' '_' | grep -q '^-\?[[:digit:]]\+$' && echo "Integer." || echo "NOT integer."

Удалите шаблон соответствия -\? в grep, если вы не принимаете отрицательное целое число.

0 голосов
/ 04 сентября 2011

Ниже приведен сценарий, написанный мной и используемый для интеграции сценариев с Nagios, и он работает до сих пор

#!/bin/bash
# Script to test variable is numeric or not
# Shirish Shukla
# Pass arg1 as number
a1=$1
a=$(echo $a1|awk '{if($1 > 0) print $1; else print $1"*-1"}')
b=$(echo "scale=2;$a/$a + 1" | bc -l 2>/dev/null)
if [[ $b > 1 ]]
then
    echo "$1 is Numeric"
else
    echo "$1 is Non Numeric"
fi

EG:

# sh isnumsks.sh   "-22.22"
-22.22 is Numeric

# sh isnumsks.sh   "22.22"
22.22 is Numeric

# sh isnumsks.sh   "shirish22.22"
shirish22.22 is Non  Numeric
0 голосов
/ 30 апреля 2009

Это немного грубо по краям, но немного более дружелюбно для новичка.

if [ $number -ge 0 ]
then
echo "Continue with code block"
else
echo "We matched 0 or $number is not a number"
fi

Это приведет к ошибке и выведет «Недопустимое число:», если $ число не число, но оно не выйдет из сценария. Как ни странно, я не нашел ни одного варианта проверки, чтобы просто проверить целое число. Логика здесь будет соответствовать любому числу, которое больше или равно 0.

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