Bash의 십진수 비교

Bash의 십진수 비교

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

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

답변이 반대표를 받았고 일종의 특이한 배시즘처럼 보인다는 점을 고려하면 이 산술 평가가 정확성에 대해 신뢰할 수 있습니까?

답변1

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

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

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

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

산출:1 -- 0

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

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

산출:1

답변2

내부는 [[...]] <문자열 비교를 위한 것입니다.

So [[ 3.56 < 2.90 ]]or [[ (3.56 < 2.90) ]]or [[ ((3.56 < 2.90)) ]]or ...는 문자열과 문자열을 어휘적으로 [[ (((3.56 < 2.90))) ]]비교하는 것입니다 (그리고 어휘적으로 는 예를 들어 보다 큽니다 ).3.562.90310

[[ 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코드 로 해석되며 예를 awk들어 명령을 실행할 수 있음 system()).

관련 정보