Bash의 십진수 비교

Bash의 십진수 비교

오늘 아침 내 검색은 bash에서 두 개의 십진수를 비교하는 방법에 관한 것이었고 다음 답변을 얻었습니다.쉘 스크립트에서 부동 소수점 숫자와 비교하는 방법. 그러나 여기에는 포함되지 않습니다.이 답변은 여기에 있습니다:

$ [[ ((3.56 < 2.90)) ]]; echo $?
1
$ [[ ((3.56 < 4.90)) ]]; echo $?
0

이 답변이 반대표를 받았고 다소 비정상적으로 굴욕적인 것처럼 보인다는 점을 고려할 때, 이 산술 평가의 정확성을 신뢰할 수 있습니까?

답변1

bash부동 소수점 숫자를 이해하지 못합니다. 매뉴얼 페이지, 섹션
인용bash산술 평가:

평가는 고정 너비 정수 [...]로 수행됩니다.

그래서 ((3 < 4))or 는 ((3 < 2))실제로 올바른 산술 표현입니다. 다음을 입력할 수 있습니다:

$ echo "$((3 < 4)) -- $((3 < 2))"

산출:1 -- 0

그러나 $ echo $((3.3 < 3.6))구문 오류 메시지가 반환됩니다. 귀하의 예에서는 실제로 문자열을 비교하고 있습니다. 다음은 몇 가지 예입니다.

$ [[ ((3.56 < 04.90)) ]]; echo $?

산출:1

답변2

[[...]] <문자열 비교에 사용됩니다 .

따라서 [[ 3.56 < 2.90 ]]or 또는 [[ (3.56 < 2.90) ]]or [[ ((3.56 < 2.90)) ]]or [[ (((3.56 < 2.90))) ]]...는 3.56문자열을 2.90어휘적으로(어휘적으로, 예를 들어 3보다 큼) 문자열과 비교합니다.10

[[ 3 -lt 2 ]]정수 비교의 경우 또는 입니다 (( 3 < 2 )). 부동 소수점 비교를 원하면 가 필요합니다. ksh93또는 zsh또는 같은 yash외부 유틸리티는 그렇게 할 수 없습니다.awkperlbash

예를 들어 다음과 같은 함수를 정의할 수 있습니다.

compare() (IFS=" "
  exec awk "BEGIN{if (!($*)) exit(1)}"
)

다음과 같이 사용할 수 있습니다.

if compare '1.5*10 < 1e3'; then
  echo less
fi

아니면 심지어 이것을 위해서도:

if compare '"bar" < "foo"'...

문자열 비교를 수행합니다.

제어되지 않은 외부 제공 데이터를 이 함수에 전달하지 마십시오. compare이는 명령 주입 취약점을 구성합니다. 데이터는 예를 들어 명령을 실행하는 데 사용할 수 있는 awk코드 로 해석됩니다.awksystem()

관련 정보