/ bin / dash : $ 1이 숫자인지 확인


12

$ 1이 / bin / dash의 정수인지 확인하는 가장 좋은 방법은 무엇입니까?

bash에서 나는 할 수 있었다 :

[[ $1 =~ ^([0-9]+)$ ]]

그러나 POSIX를 준수하지 않는 것으로 보이며 대시는이를 지원하지 않습니다.

답변:


12

다음은 양수 또는 음수의 정수를 감지 dash하고 POSIX에서 작동 하며 POSIX입니다.

옵션 1

echo "$1" | grep -Eq '^[+-]?[0-9]+$' && echo "It's an integer"

옵션 2

case "${1#[+-]}" in
    ''|*[!0-9]*)
        echo "Not an integer" ;;
    *)
        echo "Integer" ;;
esac

또는 :(nop) 명령을 약간 사용하여 :

! case ${1#[+-]} in *[!0-9]*) :;; ?*) ! :;; esac && echo Integer

5
문자열에 줄 바꿈이 포함되어 있으면 어떻게됩니까? foo\n123\nbar정수는 아니지만이 테스트를 통과합니다.
godlygeek

3
grep 버전입니다. 케이스 버전이 올바르게 보입니다.
godlygeek

5

여부 dash, bash, ksh, zsh, POSIX sh, 또는 posh( "Bourne 쉘의 재 구현" sh ); case구조는 가장 널리 사용하고 신뢰할 수 :

case $1 in (*[!0-9]*|"") false ;; (*) true ;; esac

아래에서 이것을 테스트 했습니까 dash? 그것은 나를 위해 작동 bash하지만 아닙니다 dash.
John1024

예, 시스템에서도 테스트했습니다 dash. echo $?case 명령 뒤에 추가 한 결과를 조사합니다 .
Janis

나는 똑같이 (데비안 안정)했지만 기쁨은 없었습니다. 대시 아래에서 나에게 맞는 완전한 예제는 옵션 2를 참조하십시오 .
John1024

흠, 나는 테스트 할 수있는 독창적 인 본 껍질이 없습니다. 내가 "본 쉘에없는 기능 (ksh)"에 대해 조사한 문서는 적어도 언급하지 않았으므로 거기에 있다고 가정합니다. 아니? -그런 다음 괄호를 생략하십시오. -OTOH posh( "Bourne 쉘의 재 구현")도이 솔루션에 아무런 문제가 없습니다.
Janis

1
@mikeserv; 항상 일치하는 괄호를 사용하는 데는 몇 가지 이유가 있습니다 case. 한 가지 이유는 설명하는 버그이며, 또 다른 이유는 일치하는 괄호 (vim)에 의존하는 기능이있는 편집기에서 훨씬 더 나은 지원을 제공하는 것입니다. -WRT posh는 POSIX입니다. 글쎄, 내가 준 매뉴얼 페이지의 인용문은 다른 것을 제안했지만 어쨌든 그러한 비공식적 진술에 의존 할 수는 없다고 생각합니다. 우리가 POSIX 시대에 있기 때문에 오래된 본 쉘은 더 이상 그렇게 중요하지 않습니다.
Janis

1

-eq문자열 자체 에서 테스트를 사용할 수 있습니다 .

$ dash -c 'a="a"; if [ "$a" -eq "$a" ] ; then echo number; else echo not a number; fi' 
dash: 1: [: Illegal number: a
not a number
$ dash -c 'a="0xa"; if [ "$a" -eq "$a" ] ; then echo number; else echo not a number; fi'
dash: 1: [: Illegal number: 0xa
not a number
$ dash -c 'a="-1"; if [ "$a" -eq "$a" ] ; then echo number; else echo not a number; fi'
number

오류 메시지가 문제인 경우 오류 출력을 /dev/null다음으로 리디렉션하십시오 .

$ dash -c 'a="0xa"; [ "$a" -eq "$a" ] 2>/dev/null|| echo no'
no

1
또한 그것은 " 023 "숫자 라고 말합니다 . 피연산자가 노트 십진 정수인 경우 동작이 지정되지 않으므로 대시와 함께 작동하지만 다른 모든 POSIX 쉘은 아닙니다. 예를 들어 ksh를 사용하면 SHLVL또는 라고 말합니다 1+1.
Stéphane Chazelas

0

산술 확장으로 사용 해보고 작동하는지 확인하십시오. 실제로 산술 확장은 앞뒤 공백을 무시하기 때문에 그보다 조금 더 엄격해야합니다. 산술 확장도 수행하고 확장 된 결과가 원래 변수와 정확히 일치하는지 확인하십시오.

check_if_number()
{
    if [ "$1" = "$((${1}))" ] 2>/dev/null; then
        echo "Number!"
    else
        echo "not a number"
    fi
}

음수를 사용할 수도 있습니다. 실제로 제외하려는 경우 추가 검사를 추가하십시오 $((${1} >= 0)).


1
대시가 없습니다[[
glenn jackman

@glennjackman Whoops. 있습니까 $(( ... ))? 그렇다면 내 대답은 여전히 ​​정확해야합니다. 견적을 추가하면됩니다.
godlygeek

그것은 당신의 대답입니다 : 찾아보세요.
glenn jackman

업데이트 된 버전이 트릭을 수행해야합니다. 그래도 테스트 할 대시가 없으므로 다른 것을 놓친 경우 알려주십시오.
godlygeek

나는 시도했다 : check_if_number 1.2그리고 함수는 반환 : dash: 3: arithmetic expression: expecting EOF: "1.2"
John1024

0

아마도 expr?

if expr match "$1" '^\([0-9]\+\)$' > /dev/null; then
  echo "integer"
else 
  echo "non-integer"
fi

POSIX 도 match아닙니다 \+. 또한 0은 숫자가 아니라고 말합니다. 당신은expr "x$1" : 'x[0-9]\{1,\}$'
Stéphane Chazelas

0

POSIX 시스템에서는 expr 을 사용할 수 있습니다 :

$ a=a
$ expr "$a" - 0 >/dev/null 2>&1
$ [ "$?" -lt 2 ] && echo Integer || echo Not Integer

0은 정수가 아니라고 말하면 -12는 OP의 bash 솔루션이 거부 한 것입니다. 일부 expr구현에서는 9999999999999999999가 정수가 아니라고 말합니다. POSIX는 이것이 작동한다고 보증하지 않습니다. 실제로 GNU 시스템에서는 "길이"가 정수라고 말합니다.
Stéphane Chazelas

내 테스트에서는 적어도 데비안과 OSX에서 작동합니다. Posix는 $ a가 expr 수행에 유효한 표현식 (정수)이어야 함을 보장합니다.
cuonglm

오 예, 죄송합니다. $ 테스트를 간과 했습니까? <2. 아직도 expr 9999999999999999999 + 0나에게 3 종료 상태를 제공하고 expr -12 + 0그리고 expr length + 0나에게 GNU의 EXPR와 0 종료 상태 줄 ( + stringstringGNU와 문자열로 간주하기를 expr. expr "$a" - 0잘 작동 것입니다).
Stéphane Chazelas

@ StéphaneChazelas : 예, 제 답변을 업데이트했습니다. 나는 -12유효한 정수 라고 생각 9999999999999999999하고 오버플로를주었습니다.
cuonglm

0

다음은 muru 의 답변 과 동일한 방법을 사용하는 간단한 함수입니다 .

IsInteger()      # usage: IsInteger string
{               #  returns: flag
        [ "$1" -eq "$1" ] 2> /dev/null
}

예:

p= n=2a3; IsInteger $n || p="n't" ; printf "'%s' is%s an integer\n" "$n" "$p"
p= n=23;  IsInteger $n || p="n't" ; printf "'%s' is%s an integer\n" "$n" "$p"

산출:

'2a3' isn't an integer
'23' is an integer
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.