IT

유효한 정수인지 테스트

lottoking 2020. 8. 9. 09:17
반응형

유효한 정수인지 테스트


나는 충분히 일반적인 시도하고있다 : 쉘 펼쳐보기에서 사용자 입력을 파싱하라. 사용자가 유효한 정수를 제공 한 경우 펼쳐지는 한 가지 작업을 수행하고 유효하지 않은 경우 다른 작업을 수행합니다. 문제는 수행을 수행하는 절차 (합리적으로 우아한) 방법을 찾지 못했어요. 문자별로 구분할 필요가 없습니다.

이게 쉬울 거라는 건 알지만 방법은 모르겠어요. 12 개 언어로 할 수 있습니다 BASH는 아닙니다!

내 연구에서 나는 발견했습니다.

인증서가 10 진법의 유효한 실수로 구성되어 있는지 테스트하기위한 정규식

그리고 거기에 정규식에 대해 이야기하는 대답이 내가 아는 한 그것은 C에서 사용할 수있는 함수입니다. 그래도 좋은 대답처럼 보였기 때문에 grep으로 시도했지만 grep은 어떻게 해야할지 몰랐습니다. 나는 내 상자에서 PERL 정규 취급으로하는 것을 의미하는 -P를 시도했습니다. 대시 E (-E)도 작동하지 않습니다. 그리고 -F도 마찬가지입니다.

명확하게 말하면, 나는 이와 같은 것을 시도하고 출력을 찾고 있습니다. 거기에서 내가 얻는 모든 것을 활용하기 위해 펼쳐서 해킹 할 것입니다. (IOW, 유효한 라인이 반복되는 동안 부적합한 입력은 아무것도 반환하지 않을 것입니다.)

snafu=$(echo "$2" | grep -E "/^[-+]?(?:\.[0-9]+|(?:0|[1-9][0-9]*)(?:\.[0-9]*)?)$/")
if [ -z "$snafu" ] ;
then
   echo "Not an integer - nothing back from the grep"
else
   echo "Integer."
fi

누군가가 가장 쉬운 방법을 설명 해주시겠습니까?

솔직히 TEST의 단점이라고 생각합니다. 다음과 같은 플래그가 있어야합니다.

if [ -I "string" ] ;
then
   echo "String is a valid integer."
else
   echo "String is not a valid integer."
fi

[[ $var =~ ^-?[0-9]+$ ]]
  • ^입력 패턴의 시작을 시작합니다.
  • -리터럴 "-"
  • ?수단 "0 또는 1 항 ( -)"
  • +수단 "앞의 1 이상 ( [0-9])"
  • $입력 패턴의 끝을 형성합니다

따라서 정규식은 선택 사항 -(음수의 경우)과 하나 이상의 십진수를 일치 합니다.

참고 문헌 :


와우 ... 여기에 좋은 해결책이 너무 많이 !! 위의 모든 솔루션 중에서 -eq하나의 라이너 를 사용하는 것이 가장 멋지다는 @nortally에 동의합니다 .

GNU bash, 버전 4.1.5(Debian)을 실행 입니다. ksh (SunSO 5.10) 그것을 확인했습니다.

$1정수인지 아닌지 확인하는 내 버전은 다음과 같습니다 .

if [ "$1" -eq "$1" ] 2>/dev/null
then
    echo "$1 is an integer !!"
else
    echo "ERROR: first parameter must be an integer."
    echo $USAGE
    exit 1
fi

"+"(예 : +30) 접두사를 허용합니다.

결과 :

$ int_check.sh 123
123 is an integer !!

$ int_check.sh 123+
ERROR: first parameter must be an integer.

$ int_check.sh -123
-123 is an integer !!

$ int_check.sh +30
+30 is an integer !!

$ int_check.sh -123c
ERROR: first parameter must be an integer.

$ int_check.sh 123c
ERROR: first parameter must be an integer.

$ int_check.sh c123
ERROR: first parameter must be an integer.

Ignacio Vazquez-Abrams가 제공하는 한 솔루션은 설명 된 후에도 매우 깔끔했습니다 (정규식을 좋아한다면). 그러나 +접두사 가있는 양수를 처리하지 않고 다음과 같이 쉽게 처리 할 수 ​​있습니다.

[[ $var =~ ^[-+]?[0-9]+$ ]]

여기 파티에 후발. 가장 간단하고 빠르며 스마트 한 뛰어난 솔루션을 제공합니다. case문.

case ${variable#[-+]} in
  *[!0-9]* | '') echo Not a number ;;
  * ) echo Valid number ;;
esac

비교하기 전에 모든 기호를 잘라내는 것은 약간의 해킹처럼 느껴지지만 사례에 대한 표현이 훨씬 더 간단 해집니다.


Bash 3.1 이전 버전으로의 이식성을 위해 ( =~테스트가 도입 때 ) expr.

if expr "$string" : '-\?[0-9]\+$' >/dev/null
then
  echo "String is a valid integer."
else
  echo "String is not a valid integer."
fi

expr STRING : REGEXSTRING의 시작 부분에 고정 된 REGEX를 검색하여 첫 번째 그룹 (또는 일치하지 않는 경우 일치 길이)을 반영하고 성공 / 실패를 반환합니다. 이미 오래된 정규식 구문 초과 \. -\?"아마도 -"를 [0-9]\+의미하고 "하나 이상의 숫자" $의미하며 "문자열의 끝"을 의미합니다.

Bash는 또한 확장 된 glob을 지원하지만 어떤 버전에서 이후 버전인지 기억하지 못합니다.

shopt -s extglob
case "$string" of
    @(-|)[0-9]*([0-9]))
        echo "String is a valid integer." ;;
    *)
        echo "String is not a valid integer." ;;
esac

# equivalently, [[ $string = @(-|)[0-9]*([0-9])) ]]

@(-|)" -또는 아무것도", [0-9]" 숫자 "를 *([0-9])의미하고 "0 개 이상의 숫자"를 의미합니다.


-eq테스트를 사용하는 솔루션이 마음에 씁니다. 기본적으로 한 줄짜리이기 때문입니다.

내 모든 후속은 변수 확장을 사용하여 숫자를 버리고 남은 것이 확인하는 것이 었습니다. (저는 아직 3.0 사용하고 있으며을 사용하지 않았 [[거나 expr이전에 사용했지만 만나서 반갑습니다.)

if [ "${INPUT_STRING//[0-9]}" = "" ]; then
  # yes, natural number
else
  # no, has non-numeral chars
fi

여기에 또 다른 방법이 있습니다 (테스트 내장 명령과 반환 코드 만 사용).

function is_int() { return $(test "$@" -eq "$@" > /dev/null 2>&1); } 

input="-123"

if $(is_int "${input}");
then
   echo "Input: ${input}"
   echo "Integer: $[${input}]"
else
   echo "Not an integer: ${input}"
fi

숫자가 아닌 것을 제거하고 수 있습니다. 다음은 견본 펼쳐보기입니다.

for num in "44" "-44" "44-" "4-4" "a4" "4a" ".4" "4.4" "-4.4" "09"
do
    match=${num//[^[:digit:]]}    # strip non-digits
    match=${match#0*}             # strip leading zeros
    echo -en "$num\t$match\t"
    case $num in
        $match|-$match)    echo "Integer";;
                     *)    echo "Not integer";;
    esac
done

테스트 출력은 다음과 가변합니다.

44 44 정수
-44 44 정수
44-44 정수 아님
4-4 44 정수 아님
a4 4 정수 아님
4a 4 정수 아님
.4 4 정수 아님
4.4 44 정수 아님
-4.4 44 정수 아님
09 9 정수 아님

에게 추론 간단한 저 해결책은 (())표현식 내부에서 변수를 사용하는 을 구석으로입니다.

if ((VAR > 0))
then
  echo "$VAR is a positive integer."
fi

물론이 솔루션은 0 값이 애플리케이션에 적합하지 않은 경우에만 유효합니다. 그것은 제 경우에 사실이었고 이것은 다른 솔루션보다 훨씬 간단합니다.

주석에서 지적했듯이 이로 인해 코드 실행 공격을받을 수 있습니다. (( ))연산자 는 bash (1) 매뉴얼 페이지 섹션에 VAR명시된대로를 평가 합니다 . 따라서의 내용의 출처 가 불확실 할 때이 기술 을 사용해서는 안됩니다 (물론 다른 형태의 변수 확장을 사용해서는 안됩니다).Arithmetic EvaluationVAR


또는 sed :

   test -z $(echo "2000" | sed s/[0-9]//g) && echo "integer" || echo "no integer"
   # integer

   test -z $(echo "ab12" | sed s/[0-9]//g) && echo "integer" || echo "no integer"
   # no integer

Ignacio Vazquez-Abrams의 답변에 추가합니다. 이렇게하면 + 기호가 정수 앞에 올 수 있으며 소수점으로 모든 0을 허용합니다. 예를 들어 +45.00000000을 정수로 간주 할 수 있습니다.
그러나 $ 1은 소수점을 포함하도록 형식화되어야합니다. 45는 여기서 정수로 간주되지 않지만 45.0은 정수로 간주됩니다.

if [[ $1 =~ ^-?[0-9]+.?[0]+$ ]]; then
    echo "yes, this is an integer"
elif [[ $1 =~ ^\+?[0-9]+.?[0]+$ ]]; then
    echo "yes, this is an integer"
else
    echo "no, this is not an integer"
fi

웃음을 위해 나는 대략 빠르게 이것을 수행하기 위해 일련의 함수 (is_string, is_int, is_float, is alpha string 또는 기타)를 알아 냈지만이를 수행하는 더 효율적인 (더 적은 코드) 방법이 있습니다.

#!/bin/bash

function strindex() {
    x="${1%%$2*}"
    if [[ "$x" = "$1" ]] ;then
        true
    else
        if [ "${#x}" -gt 0 ] ;then
            false
        else
            true
        fi
    fi
}

function is_int() {
    if is_empty "${1}" ;then
        false
        return
    fi
    tmp=$(echo "${1}" | sed 's/[^0-9]*//g')
    if [[ $tmp == "${1}" ]] || [[ "-${tmp}" == "${1}" ]] ; then
        #echo "INT (${1}) tmp=$tmp"
        true
    else
        #echo "NOT INT (${1}) tmp=$tmp"
        false
    fi
}

function is_float() {
    if is_empty "${1}" ;then
        false
        return
    fi
    if ! strindex "${1}" "-" ; then
        false
        return
    fi
    tmp=$(echo "${1}" | sed 's/[^a-z. ]*//g')
    if [[ $tmp =~ "." ]] ; then
        #echo "FLOAT  (${1}) tmp=$tmp"
        true
    else
        #echo "NOT FLOAT  (${1}) tmp=$tmp"
        false
    fi
}

function is_strict_string() {
    if is_empty "${1}" ;then
        false
        return
    fi
    if [[ "${1}" =~ ^[A-Za-z]+$ ]]; then
        #echo "STRICT STRING (${1})"
        true
    else
        #echo "NOT STRICT STRING (${1})"
        false
    fi
}

function is_string() {
    if is_empty "${1}" || is_int "${1}" || is_float "${1}" || is_strict_string "${1}" ;then
        false
        return
    fi
    if [ ! -z "${1}" ] ;then
        true
        return
    fi
    false
}
function is_empty() {
    if [ -z "${1// }" ] ;then
        true
    else
        false
    fi
}

여기 몇 가지 테스트를 통해 -44는 int이지만 44-는 그렇지 않다고 정의했습니다. :

for num in "44" "-44" "44-" "4-4" "a4" "4a" ".4" "4.4" "-4.4" "09" "hello" "h3llo!" "!!" " " "" ; do
    if is_int "$num" ;then
        echo "INT = $num"

    elif is_float "$num" ;then
        echo "FLOAT = $num"

    elif is_string "$num" ; then
        echo "STRING = $num"

    elif is_strict_string "$num" ; then
        echo "STRICT STRING = $num"
    else
        echo "OTHER = $num"
    fi
done

산출:

INT = 44
INT = -44
STRING = 44-
STRING = 4-4
STRING = a4
STRING = 4a
FLOAT = .4
FLOAT = 4.4
FLOAT = -4.4
INT = 09
STRICT STRING = hello
STRING = h3llo!
STRING = !!
OTHER =  
OTHER = 

참고 : 선행 0은 8 진수와 같은 숫자를 추가 할 때 다른 것을 추론 할 수 있으므로 '09'를 int로 처리하려는 경우 제거하는 것이 좋습니다 (예 : expr 09 + 0sed로 제거).

참고 URL : https://stackoverflow.com/questions/2210349/test-whether-string-is-a-valid-integer

반응형