변수를 문자열 또는 int로 비교할 때 큰 차이점이 있습니까?


22

호기심에서 bash 변수 비교 (값은 integer)를 수행 할 때 an int또는 a로 선언 된 미리 정의 된 일부 값에 대해 테스트 할 수 있습니다 string.

샘플 스크립트 :

#!/bin/bash
f1()
{
        [ "$1" == "1" ] && echo "$FUNCNAME: \"1\" compared as string"
}

f2()
{
        [[ "$1" -eq 1 ]] && echo "$FUNCNAME: \"1\" compared as int"
}

f1 $1
f2 $1

출력 :

$  ./param.sh 1
f1: "1" compared as string
f2: "1" compared as int

$  ./param.sh blah
$

두 함수 모두 같은 방식으로 작동하므로 정수 변수를 확인할 때 선호되는 방법이 있는지 궁금합니다. 나는 확인을 위해 갈 것이다 intint더 엄격한의로하지만, 그것을 수행하는 모든 그리기 백업이 있는지 궁금 string?

이 경우 f2()비교에 대해 더 엄격합니다. 즉, 10 진수 값을 전달하면 f1()문제가 해결 되지만 문제는 없습니다.


Bash에는 실제로 Integer 데이터 유형이 없습니다. 기본적으로 Bash에게 문자열을 정수로 취급하도록 힌트를 줄 수 있습니다.
helpermethod

답변:


18

그렇습니다. 많은 차이점이 있습니다. 예를 들어, =정확한 문자열 동등성을 검사하지만 -eq동등성을 검사하기 전에 두 표현식을 산술적으로 평가합니다.

$ [ " 1 " -eq 1 ] && echo equal || echo not
equal
$ [ " 1 " = 1 ] && echo equal || echo not
not

$ [ +1 -eq 1 ] && echo equal || echo not
equal
$ [ +1 = 1 ] && echo equal || echo not
not

$ [ "0+1" -eq 1 ] && echo equal || echo not
equal
$ [ "0+1" = 1 ] && echo equal || echo not
not

또한 빈 문자열은 숫자가 0과 같습니다.

$ [ "" -eq 0 ] && echo equal || echo not
equal
$ [ "" = 0 ] && echo equal || echo not
not

당신이 비교 연산자를 가져올 때 차이의 완전히 다른 클래스가 나타납니다 - 고려 <-lt, 예를 들면 :

$ [[ 2 -lt 10 ]] && echo less || echo not
less
$ [[ 2 < 10 ]] && echo less || echo not
not

이는 문자열 "2"가 문자열 "10"뒤의 알파벳순 (1이 2보다 앞에 있기 때문에)이기 때문에 숫자 "2"는 숫자 "10"보다 숫자가 작기 때문입니다.


2
(( ... ))숫자 연산 도 있다는 것을 잊지 마십시오 . (( " 1 " == 1 )) && echo yes || echo no결과yes
Patrick

7

정수 대 문자열 비교는 다음보다 크거나 작게 비교할 때 가장 중요합니다.

#!/bin/bash

eleven=11
nine=9

[[ $nine < $eleven ]] && echo string   # fail

[[ "$nine" -lt "$eleven" ]] && echo integer # pass

사전 식으로 정렬하면 9가 11 뒤에 오므로 첫 번째는 실패합니다.

따옴표를 사용한다고해서 문자열이나 숫자를 비교하는지 여부는 결정되지 않습니다. 위의 따옴표를 추가하거나 제거해도 아무런 차이가 없습니다. Bash는 대괄호 안에 정의되지 않은 변수를 포착하므로 따옴표가 필요하지 않습니다. 숫자 테스트에 작은 괄호와 함께 따옴표를 사용하면 다음과 같은 이유로 절약 할 수 없습니다.

[ "" -lt 11 ]

어쨌든 오류입니다 ( "정수 표현식 필요"). 따옴표는 대괄호로 문자열을 비교하는 효과적인 보호 수단입니다.

[ "" \< 11 ]

내 주 를 두 번 , 괄호 ""것이다 -eq 0하지만 == 0.


1
bash에서는 큰 괄호 안에 변수를 인용 할 필요가 없습니다. 내장 [[변수는 변수가있는 위치를 기억할만큼 똑똑하고 빈 변수에 속지 않습니다. 작은 괄호 ( [)에는이 기능이 없으며 따옴표가 필요합니다.
glenn jackman

@glennjackman 그 사실을 알지 못했습니다. [[ -lt 11 ]]오류는 아니지만 nothing=; [[ $nothing -lt 11 ]]그렇지 않습니다. 마지막 단락을 약간 재 작업했습니다.
goldilocks

2

말한 것 외에도.
쉘 스크립팅에서는 빠른 계산이 필요한 경우는 드물지만 숫자를 사용하면 동등성을 비교하는 것이 더 빠릅니다.

$ b=234
$ time for ((a=1;a<1000000;a++)); do [[ $b = "234" ]]; done

real    0m13.008s
user    0m12.677s
sys 0m0.312s

$ time for ((a=1;a<1000000;a++)); do [[ $b -eq 234 ]]; done

real    0m10.266s
user    0m9.657s
sys 0m0.572s

그들이 다른 일을한다는 것을 고려할 때, 나는 성능이 관련이 없다고 말하고 싶습니다. 원하는 것을하는 것을 사용해야합니다.
godlygeek

@godlygeek 변수의 평등 비교는 양방향으로 달성 할 수 있습니다. "-eq"가 빠릅니다.
Emmanuel

그들은 평등의 다른 정의를 테스트합니다. "이 변수에 정확한 문자열 123이 포함되어 있습니까?"라는 질문에 대답하려면 "+123"에 대해 =사용하는 -eq것과 일치하기 때문에를 사용할 수 있습니다. "이 변수가 산술 연산 식으로 평가 될 때 123과 비교합니다"를 알고 싶다면을 사용할 수 있습니다 -eq. 프로그래머가 어디에서 평등의 정의를 사용하지 않았는지 알 수있는 유일한 시간은 변수의 내용이 미리 특정 패턴으로 제한되어 있음을 알 때입니다.
godlygeek

@godlygeek 흥미롭게도, 문제는 숫자가 문자열 인 것처럼 평등을 비교하는 것에 관한 것이 었습니다. 변수가 특정 패턴으로 미리 제한되어있는 경우에 적합합니까?
Emmanuel

귀하의 예 ( b=234)는 해당 패턴에 적합합니다-직접 할당했기 때문에 +234 또는 "234"또는 "233 + 1"이 아니라는 것을 알고 있으므로 문자열과 숫자로 비교하는 것도 동일합니다. 그러나 OP의 스크립트는 명령 줄 인수로 입력을 ./param.sh 0+1./param.sh " 1"
받기
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.