Programming

Bash에서 변수가 숫자인지 어떻게 테스트합니까?

procodes 2020. 2. 10. 22:29
반응형

Bash에서 변수가 숫자인지 어떻게 테스트합니까?


스크립트에 전달 된 인수가 숫자인지 확인하는 방법을 알 수 없습니다.

내가하고 싶은 것은 다음과 같습니다.

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

어떤 도움?


한 가지 방법은 다음과 같이 정규식을 사용하는 것입니다.

re='^[0-9]+$'
if ! [[ $yournumber =~ $re ]] ; then
   echo "error: Not a number" >&2; exit 1
fi

값이 반드시 정수가 아닌 경우 정규식을 적절히 수정하십시오. 예를 들어 :

^[0-9]+([.][0-9]+)?$

... 또는 부호가있는 숫자를 처리하려면 :

^[+-]?[0-9]+([.][0-9]+)?$

bashisms없이 (System V sh에서도 작동)

case $string in
    ''|*[!0-9]*) echo bad ;;
    *) echo good ;;
esac

이것은 빈 문자열과 숫자가 아닌 문자열을 거부하고 다른 모든 것을 허용합니다.

음수 또는 부동 소수점 숫자는 추가 작업이 필요합니다. 아이디어는 첫 번째 "나쁜"패턴에서 -/ 를 제외 .하고 부적절한 사용 ( ?*-*/ *.*.*)을 포함하는 "나쁜"패턴을 더 추가하는 것입니다 ( / )


정규식없이 Bourne과 같은 기본 셸에서 다음 솔루션을 사용할 수도 있습니다. 기본적으로 숫자가 아닌 숫자를 사용하는 숫자 값 평가 작업은 쉘에서 오류로 암시 적으로 암시됩니다.

"$var" -eq "$var"

에서와 같이 :

#!/bin/bash

var=a

if [ -n "$var" ] && [ "$var" -eq "$var" ] 2>/dev/null; then
  echo number
else
  echo not a number
fi

당신은 또한 $를 테스트 할 수 있습니까? 보다 명백한 오퍼레이션의 리턴 코드 :

[ -n "$var" ] && [ "$var" -eq "$var" ] 2>/dev/null
if [ $? -ne 0 ]; then
   echo $var is not number
fi

표준 오류의 리디렉션은 숫자가없는 경우 bash가 출력하는 "정수 식 예상"메시지를 숨기는 것입니다.

주의 사항 (아래 의견 감사) :

  • 소수점이있는 숫자는 유효한 "숫자"로 식별 되지 않습니다.
  • [[ ]]대신에 사용 [ ]하면 항상true
  • 비 Bash 쉘은 대부분이 표현식을 다음과 같이 평가합니다. true
  • Bash의 동작은 문서화되어 있지 않으므로 경고없이 변경 될 수 있습니다.
  • 숫자에 공백이 포함 된 경우 (예 : "1 a") 다음과 같이 오류가 발생합니다. bash: [[: 1 a: syntax error in expression (error token is "a")
  • 값이 var-name과 같은 경우 (예 : i = "i") 다음과 같은 오류가 발생합니다. bash: [[: i: expression recursion level exceeded (error token is "i")

이것은 숫자가 음이 아닌 정수이고 쉘과 독립적이며 (bashisms 없음) 쉘 내장만을 사용하는지 테스트합니다.

부정확합니다.

이 첫 번째 답변 (아래)은 변수에서 첫 번째가 아닌 한 문자가있는 정수를 허용합니다.

[ -z "${num##[0-9]*}" ] && echo "is a number" || echo "is not a number";

맞습니다 .

jilles그의 답변 에서 언급하고 제안한 것처럼 이것은 쉘 패턴을 사용하여 올바른 방법입니다.

[ ! -z "${num##*[!0-9]*}" ] && echo "is a number" || echo "is not a number";

아무도 bash의 확장 패턴 일치를 제안하지 않았습니다 .

[[ $1 == ?(-)+([0-9]) ]] && echo "$1 is an integer"

쉘에서 숫자 형식을 직접 구문 분석하는 솔루션에 놀랐습니다. 쉘은 파일과 프로세스를 제어하기위한 DSL 인 이것에 적합하지 않습니다. 예를 들어 다음과 같이 충분한 수의 파서가 있습니다.

isdecimal() {
  # filter octal/hex/ord()
  num=$(printf '%s' "$1" | sed "s/^0*\([1-9]\)/\1/; s/'/^/")

  test "$num" && printf '%f' "$num" >/dev/null 2>&1
}

'% f'를 필요한 특정 형식으로 변경하십시오.


나는 대답을보고 있었고 ... 아무도 플로트 번호에 대해 생각하지 않았다는 것을 깨달았습니다 (점 포함)!

grep을 사용하는 것도 좋습니다.
-E는 확장 된 expexp를
의미합니다. -q는 조용함을 의미합니다 (반향되지 않음)
.

명령 행에서 직접 테스트하려면 다음을 수행하십시오.

$ echo "32" | grep -E ^\-?[0-9]?\.?[0-9]+$  
# answer is: 32

$ echo "3a2" | grep -E ^\-?[0-9]?\.?[0-9]+$  
# answer is empty (false)

$ echo ".5" | grep -E ^\-?[0-9]?\.?[0-9]+$  
# answer .5

$ echo "3.2" | grep -E ^\-?[0-9]?\.?[0-9]+$  
# answer is 3.2

bash 스크립트에서 사용 :

check=`echo "$1" | grep -E ^\-?[0-9]*\.?[0-9]+$`

if [ "$check" != '' ]; then    
  # it IS numeric
  echo "Yeap!"
else
  # it is NOT numeric.
  echo "nooop"
fi

JUST 정수와 일치 시키려면 다음을 사용하십시오.

# change check line to:
check=`echo "$1" | grep -E ^\-?[0-9]+$`

@mary까지 추적하십시오. 그러나 담당자가 충분하지 않으므로 해당 게시물에 대한 의견으로 게시 할 수 없습니다. 어쨌든, 여기 내가 사용한 것이 있습니다 :

isnum() { awk -v a="$1" 'BEGIN {print (a == a + 0)}'; }

인수가 숫자이면 함수는 "1"을 리턴하고 그렇지 않으면 "0"을 리턴합니다. 이것은 부동 소수점뿐만 아니라 정수에서도 작동합니다. 사용법은 다음과 같습니다.

n=-2.05e+07
res=`isnum "$n"`
if [ "$res" == "1" ]; then
     echo "$n is a number"
else
     echo "$n is not a number"
fi

test -z "${i//[0-9]}" && echo digits || echo no no no

${i//[0-9]}값의 숫자를 $i빈 문자열로 바꿉니다 ( 참조) man -P 'less +/parameter\/' bash. -z결과 문자열의 길이가 0인지 확인합니다.

$i비어 있는 경우를 제외하려면 다음 구성 중 하나를 사용할 수 있습니다.

test -n "$i" && test -z "${i//[0-9]}" && echo digits || echo not a number
[[ -n "$i" && -z "${i//[0-9]}" ]] && echo digits || echo not a number

오래된 질문이지만 방금 해결책을 찾고 싶었습니다. 이것은 이상한 쉘 트릭을 필요로하지 않거나 영원히 있지 않은 것에 의존합니다.

if [ -n "$(printf '%s\n' "$var" | sed 's/[0-9]//g')" ]; then
    echo 'is not numeric'
else
    echo 'is numeric'
fi

기본적으로 입력에서 모든 숫자를 제거하고 길이가 0이 아닌 문자열로 남겨두면 숫자가 아닙니다.


http://tldp.org/LDP/Bash-Beginners-Guide/html/sect_04_03.html

bash의 문자 클래스를 사용할 수도 있습니다.

if [[ $VAR = *[[:digit:]]* ]]; then
 echo "$VAR is numeric"
else
 echo "$VAR is not numeric"
fi

숫자에는 공백, 소수점 및 부동 소수점에 대한 "e"또는 "E"가 포함됩니다.

그러나 C 스타일 16 진수 (예 : "0xffff"또는 "0XFFFF")를 지정하면 [[: digit :]]가 true를 반환합니다. 여기에 약간의 함정이 있습니다. bash를 사용하면 "0xAZ00"과 같은 작업을 수행하고 여전히 숫자로 계산할 수 있습니다 (16이 아닌 다른 기수에 대해 0x 표기법을 사용할 수있게하는 GCC 컴파일러의 이상한 기발한 것이 아닌가 ??? )

16 진수를 허용하지 않는 한 입력이 완전히 신뢰할 수없는 경우 숫자인지 테스트하기 전에 "0x"또는 "0X"를 테스트 할 수 있습니다. 그것은 다음에 의해 달성 될 것입니다 :

if [[ ${VARIABLE:1:2} = "0x" ]] || [[ ${VARIABLE:1:2} = "0X" ]]; then echo "$VAR is not numeric"; fi

아직 주석을 달 수 없으므로 bash 패턴 일치를 사용하여 glenn jackman의 답변에 대한 확장 인 내 자신의 답변을 추가 할 것입니다.

내 원래 필요는 숫자를 식별하고 정수와 부동 소수점을 구별하는 것이 었습니다. 함수 정의는 다음과 같이 차감되었습니다.

function isInteger() {
    [[ ${1} == ?(-)+([0-9]) ]]
}

function isFloat() {
    [[ ${1} == ?(-)@(+([0-9]).*([0-9])|*([0-9]).+([0-9]))?(E?(-|+)+([0-9])) ]]
}

패턴 테스트가 의도 한대로 작동하는지 확인하기 위해 단위 테스트 (shUnit2 사용)를 사용했습니다.

oneTimeSetUp() {
    int_values="0 123 -0 -123"
    float_values="0.0 0. .0 -0.0 -0. -.0 \
        123.456 123. .456 -123.456 -123. -.456
        123.456E08 123.E08 .456E08 -123.456E08 -123.E08 -.456E08 \
        123.456E+08 123.E+08 .456E+08 -123.456E+08 -123.E+08 -.456E+08 \
        123.456E-08 123.E-08 .456E-08 -123.456E-08 -123.E-08 -.456E-08"
}

testIsIntegerIsFloat() {
    local value
    for value in ${int_values}
    do
        assertTrue "${value} should be tested as integer" "isInteger ${value}"
        assertFalse "${value} should not be tested as float" "isFloat ${value}"
    done

    for value in ${float_values}
    do
        assertTrue "${value} should be tested as float" "isFloat ${value}"
        assertFalse "${value} should not be tested as integer" "isInteger ${value}"
    done

}

참고 : isFloat 패턴은 소수점 ( @(.,)) 및 E 기호 ( @(Ee))에 대해 더 관대하도록 수정할 수 있습니다 . 내 단위 테스트는 정수 또는 부동 값이지만 유효하지 않은 입력은 아닌 값만 테스트합니다.


@charles Dufy와 다른 사람들이 이미 명확한 대답을했습니다. 순수한 bash 솔루션은 다음을 사용합니다.

string="-12,345"
if [[ "$string" =~ ^-?[0-9]+[.,]?[0-9]*$ ]]
then
    echo $string is a number
else
    echo $string is not a number
fi

실수의 경우 기수 앞에 숫자가 있어야하는 것은 아닙니다 .

부동 수 및 과학적 표기법 (C / Fortran의 많은 프로그램 또는이 방법으로 부동 수출)을보다 철저하게 지원하기 위해이 행에 유용한 추가 항목은 다음과 같습니다.

string="1.2345E-67"
if [[ "$string" =~ ^-?[0-9]*[.,]?[0-9]*[eE]?-?[0-9]+$ ]]
then
    echo $string is a number
else
    echo $string is not a number
fi

따라서 특정 유형을 찾고 있다면 숫자 유형을 구별하는 방법으로 이어집니다.

string="-12,345"
if [[ "$string" =~ ^-?[0-9]+$ ]]
then
    echo $string is an integer
elif [[ "$string" =~ ^-?[0-9]*[.,]?[0-9]*$ ]]
then
    echo $string is a float
elif [[ "$string" =~ ^-?[0-9]*[.,]?[0-9]*[eE]-?[0-9]+$ ]]
then
    echo $string is a scientific number
else
    echo $string is not a number
fi

참고 : 십진수 및 과학 표기법에 대한 구문 요구 사항을 나열 할 수 있습니다. 하나는 쉼표를 기수로, "."로 허용하는 것입니다. 그런 다음 기수 지점이 하나만 있어야한다고 주장합니다. [Ee] 플로트에는 두 개의 +/- 기호가있을 수 있습니다. 나는 Aulu의 연구에서 몇 가지 규칙을 더 배우고 '' '-' '-E-1' '0-0'과 같은 잘못된 문자열에 대해 테스트했습니다. 여기 내 정규식 / 하위 문자열 / 전문가 도구가 있습니다.

parse_num() {
 local r=`expr "$1" : '.*\([.,]\)' 2>/dev/null | tr -d '\n'` 
 nat='^[+-]?[0-9]+[.,]?$' \
 dot="${1%[.,]*}${r}${1##*[.,]}" \
 float='^[\+\-]?([.,0-9]+[Ee]?[-+]?|)[0-9]+$'
 [[ "$1" == $dot ]] && [[ "$1" =~ $float ]] || [[ "$1" =~ $nat ]]
} # usage: parse_num -123.456

[[ $1 =~ ^-?[0-9]+$ ]] && echo "number"

-음수를 포함하는 것을 잊지 마십시오 !


나는 이것을 시도 할 것이다 :

printf "%g" "$var" &> /dev/null
if [[ $? == 0 ]] ; then
    echo "$var is a number."
else
    echo "$var is not a number."
fi

참고 : 이것은 nan과 inf를 숫자로 인식합니다.


가장 간단한 방법은 숫자가 아닌 문자가 포함되어 있는지 확인하는 것입니다. 모든 숫자 문자를 아무것도 바꾸지 않고 길이를 확인하십시오. 길이가 있으면 숫자가 아닙니다.

if [[ ! -n ${input//[0-9]/} ]]; then
    echo "Input Is A Number"
fi

내가 최근 에 유닛 테스트를 한 karttu의 접근 방식 과 같이 이것을 조작해야했기 때문에 . 코드를 수정하고 다른 솔루션도 추가했으며 결과를 직접 확인하십시오.

#!/bin/bash

    # N={0,1,2,3,...} by syntaxerror
function isNaturalNumber()
{
 [[ ${1} =~ ^[0-9]+$ ]]
}
    # Z={...,-2,-1,0,1,2,...} by karttu
function isInteger() 
{
 [[ ${1} == ?(-)+([0-9]) ]]
}
    # Q={...,-½,-¼,0.0,¼,½,...} by karttu
function isFloat() 
{
 [[ ${1} == ?(-)@(+([0-9]).*([0-9])|*([0-9]).+([0-9]))?(E?(-|+)+([0-9])) ]]
}
    # R={...,-1,-½,-¼,0.E+n,¼,½,1,...}
function isNumber()
{
 isNaturalNumber $1 || isInteger $1 || isFloat $1
}

bools=("TRUE" "FALSE")
int_values="0 123 -0 -123"
float_values="0.0 0. .0 -0.0 -0. -.0 \
    123.456 123. .456 -123.456 -123. -.456 \
    123.456E08 123.E08 .456E08 -123.456E08 -123.E08 -.456E08 \
    123.456E+08 123.E+08 .456E+08 -123.456E+08 -123.E+08 -.456E+08 \
    123.456E-08 123.E-08 .456E-08 -123.456E-08 -123.E-08 -.456E-08"
false_values="blah meh mooh blah5 67mooh a123bc"

for value in ${int_values} ${float_values} ${false_values}
do
    printf "  %5s=%-30s" $(isNaturalNumber $value) ${bools[$?]} $(printf "isNaturalNumber(%s)" $value)
    printf "%5s=%-24s" $(isInteger $value) ${bools[$?]} $(printf "isInteger(%s)" $value)
    printf "%5s=%-24s" $(isFloat $value) ${bools[$?]} $(printf "isFloat(%s)" $value)
    printf "%5s=%-24s\n" $(isNumber $value) ${bools[$?]} $(printf "isNumber(%s)" $value)
done

따라서 isNumber () 는 대시, 쉼표 및 지수 표기법을 포함하므로 정수 및 부동 소수점에 대해서는 TRUE를 반환합니다. 반면에 isFloat () 는 정수 값에 대해 FALSE를 반환하고 isInteger () 는 부동에 대해 FALSE를 반환합니다. 편의를 위해 하나의 라이너로 :

isNaturalNumber() { [[ ${1} =~ ^[0-9]+$ ]]; }
isInteger() { [[ ${1} == ?(-)+([0-9]) ]]; }
isFloat() { [[ ${1} == ?(-)@(+([0-9]).*([0-9])|*([0-9]).+([0-9]))?(E?(-|+)+([0-9])) ]]; }
isNumber() { isNaturalNumber $1 || isInteger $1 || isFloat $1; }

expr을 사용 합니다. 숫자가 아닌 값에 0을 추가하려고하면 0이 아닌 값을 반환합니다.

if expr -- "$number" + 0 > /dev/null 2>&1
then
    echo "$number is a number"
else
    echo "$number isn't a number"
fi

정수가 아닌 사람이 필요한 경우 bc 를 사용하는 것이 가능할 수도 있지만 bc, 똑같은 동작 이 없다고 생각 합니다. 숫자가 아닌 숫자에 0을 추가하면 0이되고 값 0도 반환합니다. 어쩌면 당신은 결합 할 수 있습니다 bcexpr. bc에 0을 추가하는 데 사용 합니다 $number. 대답이 0경우 0이 아닌지 expr확인하십시오 $number.


형식 문자열 "% 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; }


grep문제의 변수가 확장 정규식과 일치하는지 확인하기 위해을 사용하여 달성 할 수 있습니다 .

테스트 정수 1120:

yournumber=1120
if [ $(echo "$yournumber" | grep -qE '^[0-9]+$'; echo $?) -ne "0" ]; then
    echo "Error: not a number."
else
    echo "Valid number."
fi

산출: Valid number.

정수가 아닌 테스트 1120a:

yournumber=1120a
if [ $(echo "$yournumber" | grep -qE '^[0-9]+$'; echo $?) -ne "0" ]; then
    echo "Error: not a number."
else
    echo "Valid number."
fi

산출: Error: not a number.


설명

  • grep-E스위치는 우리가 확장 된 정규 표현식을 사용할 수 있습니다 '^[0-9]+$'. 이 정규 표현식은 변수 만한다는 뜻 []숫자가 포함 0-9으로부터 구를 통해 제로 ^받는 시작 $변수의 끝 이상이 있어야 +하나 개의 문자.
  • grep-q조용한 스위치는 무엇을 발견할지 여부를 모든 출력이 꺼집니다.
  • $?이전에 실행 된 명령의 종료 상태입니다. 종료 상태 0는 성공을 의미하고 더 큰 것은 오류를 의미합니다. grep명령의 종료 상태가 0일치하는 항목을 찾은 경우와 1그렇지 않은 경우를;
  • $() 우리가 다른 명령을 실행하고 출력을 사용할 수있게하는 서브 쉘입니다.

그래서에, 모두 함께 퍼팅 $()우리는 서브 쉘 echo변수 $yournumber|그에 파이프 grep에있는 -q자동 일치 스위치 -E확장 정규식 '^[0-9]+$'표현. 우리는 다음 될 종료 상태, 경우 성공적으로는 일치를 발견하고 그것을하지 않았다합니다.echo$?0grep1

이제, 외부 $()서브 쉘과 다시 if조건, 우리는 출력을, 하나 0또는 1로부터 $()서브 쉘하고 있는지 확인 -ne같지 않음 "0". 일치 1하지 않으면 종료 상태가 일치하지 않습니다 "0". 그런 다음에하겠습니다 echo "Error: not a number.". 성공적으로 일치하면 종료 상태 출력 0은 같고 "0"다른 경우에는 우리와 같습니다 echo "Valid number.".


플로트 또는 복식

float 또는 double '^[0-9]+$''^[0-9]*+\.?[0-8]+$'대해 정규식을에서 변경할 수 있습니다 .

플로트 테스트 1120.01:

yournumber=1120.01
if [ $(echo "$yournumber" | grep -qE '^[0-9]*+\.?[0-8]+$'; echo $?) -ne "0" ]; then
    echo "Error: not a number."
else
    echo "Valid number."
fi

산출: Valid number.

플로트 테스트 11.20.01:

yournumber=11.20.01
if [ $(echo "$yournumber" | grep -qE '^[0-9]*+\.?[0-8]+$'; echo $?) -ne "0" ]; then
    echo "Error: not a number."
else
    echo "Valid number."
fi

산출: Error: not a number.


부정적

음수를 허용하려면 정규식을에서 '^[0-9]+$'변경하십시오 '^\-?[0-9]+$'.

음수 부동 수 또는 복식 수를 허용하려면 정규식을에서 '^[0-9]*+\.?[0-8]+$'변경하십시오 '^\-?[0-9]*+\.?[0-8]+$'.


내 문제의 경우, 사용자가 실수로 텍스트를 입력하지 않도록 간단하게 읽을 수 있도록 노력해야했습니다.

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

매뉴얼 페이지에 따르면 이것은 내가 원하는 것을 거의 수행합니다.

표현식의 값이 0이 아닌 경우 리턴 상태는 0입니다.

"숫자 일 수있는"문자열에 대한 불쾌한 오류 메시지를 방지하기 위해 오류 출력을 무시합니다.

$ (( 2s ))
bash: ((: 2s: value too great for base (error token is "2s")

음수를 잡으려면 :

if [[ $1 == ?(-)+([0-9.]) ]]
    then
    echo number
else
    echo not a number
fi

"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+ 연산자를 사용하는 것을 선호합니다.


Alberto Zaccagni의 답변이 마음에 듭니다.

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

중요한 전제 조건 :-생성 된 하위 셸 없음-호출 된 RE 파서 없음-대부분의 셸 응용 프로그램은 실수를 사용하지 않습니다

그러나 $var복잡한 경우 (예 : 연관 배열 액세스) 숫자가 음이 아닌 정수 (대부분의 유스 케이스)이면 더 효율적일까요?

if [ "$var" -ge 0 ] 2> /dev/null; then ..

printf '%b' "-123\nABC" | tr '[:space:]' '_' | grep -q '^-\?[[:digit:]]\+$' && echo "Integer." || echo "NOT integer."

-\?음의 정수를 허용하지 않으면 grep 일치 패턴을 제거하십시오 .


점으로 구분 된 전체 부분과 소수 부분을 테스트하는 정규 표현식으로 동일한 작업을 수행했습니다.

re="^[0-9]*[.]{0,1}[0-9]*$"

if [[ $1 =~ $re ]] 
then
   echo "is numeric"
else
  echo "Naahh, not numeric"
fi

다음을 사용합니다 (정수).

## ##### 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

그것이 나에게 가장 실용적으로 보였기 때문에 ultrasawblade의 요리법을 시도했지만 그것을 작동시킬 수 없었습니다. 결국 나는 다른 방법으로 매개 변수 대체에 따라 다른 방법을 고안했지만 이번에는 정규식 대체로

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

$ var의 모든 : digit : 클래스 문자를 제거하고 빈 문자열이 남아 있는지 확인합니다. 이는 원본이 숫자 일뿐임을 의미합니다.

이것에 대해 내가 좋아하는 것은 작은 설치 공간과 유연성입니다. 이 형식에서는 구분되지 않은 기본 10 정수에만 작동하지만 다른 요구에 맞게 패턴 일치를 사용할 수 있습니다.


빠르다 & 더럽다 : 나는 그것이 가장 우아한 방법은 아니라는 것을 알고 있지만 일반적으로 0을 추가하고 결과를 테스트합니다. 이렇게 :

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이 정수가 아닌 경우 $ (($ 1 + 0))은 0을 반환하거나 폭탄을 반환합니다. 예를 들어 :

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의 솔루션과 Duffy의 정규식을 가지고 놀 것입니다-그것들은 bash 프레임 워크에서 가장 강력 해 보입니다 ...


나는 매우 짧은 버전을 발견했다.

function isnum()
{
    return `echo "$1" | awk -F"\n" '{print ($0 != $0+0)}'`
}

참고 : https://stackoverflow.com/questions/806906/how-do-i-test-if-a-variable-is-a-number-in-bash



반응형