programing

문자열이 유효한 정수인지 테스트

bestprogram 2023. 5. 22. 21:53

문자열이 유효한 정수인지 테스트

셸 스크립트에서 사용자 입력을 구문 분석하는 등 충분히 일반적인 작업을 수행하려고 합니다.사용자가 올바른 정수를 제공한 경우 스크립트는 한 가지 작업을 수행하고, 올바르지 않은 경우 다른 작업을 수행합니다.문제는, 저는 이것을 하는 쉬운 (그리고 상당히 우아한) 방법을 찾지 못했다는 것입니다. 저는 그것을 차로 구별하고 싶지 않습니다.

이게 쉬울 거라는 건 알지만 어떻게 해야 할지 모르겠어요.저는 12개 국어로 할 수 있지만, BASH는 할 수 없습니다!

제가 조사한 바로는 다음과 같습니다.

문자열이 기본 10의 유효한 실수로 구성되어 있는지 여부를 테스트하는 정규식

그리고 정규식에 대해 이야기하는 답이 있지만, 제가 아는 한, 그것은 (다른 것들 중에서) C에서 사용할 수 있는 기능입니다.여전히, 그것은 훌륭한 답처럼 보이는 것을 가지고 있어서 나는 grep과 함께 그것을 시도했지만, grep은 그것을 어떻게 해야 할지 몰랐습니다.나는 내 상자에 PERL regexp - nada로 처리하는 것을 의미하는 -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

누가 이것이 어떻게 가장 쉽게 이루어지는지 설명해 주시겠습니까?

솔직히, 제 생각에 이것은 시험의 단점입니다.이런 깃발이 있어야 합니다.

if [ -I "string" ] ;
then
   echo "String is a valid integer."
else
   echo "String is not a valid integer."
fi
[[ $var =~ ^-?[0-9]+$ ]]
  • ^.
  • -문자 그대로 "-"입니다.
  • ?의 "0 1앞의 0 또는 1")을 의미합니다.-)"
  • +의 (의미앞개 " 의입 " 는는 " 이그 " 상다 " 니또 " 입"다 " 상▁"니 " 미▁means이 " 의▁or개 " ▁1의1 "[0-9])"
  • $.

인 " 식은선사일치니다합과항택정규다▁an"와 일치합니다.-(음의 숫자의 경우), 그 뒤에 하나 이상의 소수 자릿수가 나옵니다.

참조:

많아요!!ㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜ에서, 는 @의 @nortal의 @nortal의 @nortal에 합니다.-eq라이너 하나가 가장 멋집니다.

bash, 나는 GNU bash를 .4.1.5(으). 5ksh(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.

이그나시오 바스케스-아브람스가 제공한 솔루션도 설명이 끝난 후 매우 깔끔했습니다.그나러, 그양숫의처않리다습니자지로 를 처리하지 .+접두사는 다음과 같이 쉽게 수정할 수 있습니다.

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

여기 파티에 늦게 온 사람.가장 간단하고, 빠르고, 가장 휴대하기 쉬운 솔루션을 언급하지 않은 것이 매우 놀랍습니다.case진술.

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

비교하기 전에 기호를 트리밍하는 것은 약간의 해킹처럼 느껴지지만, 그것은 사례 진술에 대한 표현을 훨씬 더 단순하게 만듭니다.

나는 그것을 사용하는 솔루션이 좋습니다.-eq테스트, 왜냐하면 기본적으로 하나의 라이너이기 때문입니다.

은 매개 확장을 것이 (는 3.0을 아직 하지 않았습니다. 저만은 버남숫 해는다 모니것리고것습. (3.0 아직사있용사않았다니습지하용만지고하었확)[[또는expr전에, 하지만 그들을 만나서 기쁩니다.)

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

3(Bash 3.1이 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를 검색하여 첫 번째 그룹(또는 일치하지 않는 경우 일치하는 길이)을 에코하고 성공/실패를 반환합니다.은 오래된 구문이기 regex 구문입니다.\.-\?"아마도"라는 뜻입니다.-",[0-9]\+는 "한 자리 의미하며, " 나이상를숫자의며의 " 하미하를,며의하미"▁means",$"끈의 끝"을 의미합니다.

Bash는 확장된 글러브도 지원하지만, 어떤 버전 이후인지는 기억나지 않습니다.

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자리 이상"을 의미합니다.

다음은 테스트 내장 명령어와 반환 코드를 사용하는 경우의 또 다른 예는 다음과 같습니다.

function is_int() { test "$@" -eq "$@" 2> /dev/null; } 
 
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

테스트 출력은 다음과 같습니다.

4444 정수-4444 정수44-44 정수 아님4-444 정수 아님a44 정수 아님4a4 정수 아님.44 정수 아님4.444 정수 아님-4.444 정수 아님09 9 정수 아님

은 저게가간해결내은변부다것니이습었사용는수하를 안에 있는 이었습니다.(())so:so, 다과같습다니음식.

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

물론 이 솔루션은 0 값이 애플리케이션에 적합하지 않은 경우에만 유효합니다.제 경우에도 마찬가지였고, 다른 솔루션보다 훨씬 단순합니다.

코멘트에서 지적한 바와 같이 코드 실행 공격의 대상이 될 수 있습니다.(( ))연산자 평가VAR에 기재된 바와 같이Arithmetic Evaluationbash(1) man 페이지의 섹션입니다.그러므로, 당신은 내용의 출처에 이 기술을 사용해서는 안됩니다.VAR불확실합니다(물론 다른 형태의 변수 확장도 사용해서는 안 됩니다).

또는 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가 의도이지만 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 것 같 숫 내 추 은 을 때 ' 것 예 있 하 다 를 가 할 자 추 다 니 입 것 더 것 이 을 나 거 제 하 는 가 는 각 면 할 이 생 라 고 리 처 인 참 로 expr 09 + 0 sed와 (strip with sed)

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