Bash 산술 출력 결과를 10진수로 표시

Bash 산술 출력 결과를 10진수로 표시

Bash를 사용하여 계산을 수행하고 16진수 입력을 제공하면 올바르게 계산되지만 결과는 10진수로 출력됩니다. 이게 정상인가요? 분명히 결과를 16진수로 제공하기 때문에 결과를 16진수로 표시하고 싶습니다. 이것을 바꿀 수 있는 방법이 있나요?

알아요 printf. 하지만 printf증분 등을 사용하여 변수를 약간 업데이트할 때마다 이를 호출하는 것이 이상해 보입니다.

예를 들어

echo $((0xa+1))

결과는 11내가 예상한 대로였다 b.

답변1

$((0xa+1))산술 표현식의 평가를 십진수 표현으로 확장하는 산술 확장입니다 0xa+1.

0x이 표현식 뒤에는 (16진 정수 상수), 이진 더하기 연산자 및 (10진 정수 상수) a+1가 오지 않습니다.0xa+1

내가 아는 한, Bourne과 유사한 유일한 쉘은 10 이외의 진수에서 정수 산술 확장을 수행할 수 zsh있으며 다음 구문을 사용하여 확장할 진수를 명시적으로 지정해야 합니다.

$ echo $(( [#16] 0xa + 1 ))
16#B
$ echo $(( [##16] 0xa + 1 ))
B
$ set -o c_bases
$ echo $(( [#16] 0xa + 1 ))
0xB

마찬가지로 다음을 ksh사용하여 정수 변수에 염기를 할당할 수 있습니다.

$ typeset -i16 var
$ (( var = 0xa + 1 ))
$ echo "$var"
16#B
$ set -o c_bases
$ echo "$var"
0xB

(ksh가 16#b거기에 제공되며, c_bases옵션( 옵션이 설정된 경우 가 아니라 16진수 0xBAD대신 제공됨)이 구체적입니다).16#BAD0778#77octal_zeroeszsh

또한 정수 산술 표현식( , , , , 등과 같은 산술 연산자 zsh사용) 내에서 변수를 할당하면 정수 유형을 가져오고 (진이 할당되지 않은 경우) 명시적인 기수가 있는 가장 오른쪽 정수를 상속합니다. 상수의 기본(예 : , , )입니다.=--++*=-=+=10#120x120b11

예를 들어 . (( a = 0x10 + 0b1000 ))는 값이 24인 정수 변수로 typeset -gi2 a=24정의되고 이진수( )로 확장됩니다.a$a2#11000

info zsh 'Arithmetic Evaluation'자세히보다.

bashksh에서는 복사 typeset -i하지만 복사하지는 않습니다 typeset -i<base>.

bash숫자를 10이 아닌 진수 로 변환 하려면 printf내장 함수를 사용하여 다른 사람들이 보여주듯이 8과 16을 나타내거나 ///를 사용하여 다른 진수(지원되는 진수의 범위와 그 진수의 범위)를 나타낼 수 있습니다 dc. 표현된 것은 이러한 염기 간의 차이점))입니다.bckshzsh

예를 들어, 30진수로 변환하려면 다음을 수행하세요.

base30_dc() { echo "30o $1 p" | dc; }
base30_bc() { echo "obase=30; $1" | bc; }
base30_ksh93() { ksh93 -c 'printf "%..30d\n" "$@"' ksh "$@"; }
base30_zsh() { zsh -c 'echo $(([##30] $1))' zsh "$1"; }

다음을 제공합니다.

$ base30_dc 1234
 01 11 04
$ base30_bc 1234
 01 11 04
$ base30_ksh93 1234
1b4
$ base30_zsh 1234
1B4

그러나 음수 상수는 dc부호로 표시됩니다. _while은 -이진 빼기 연산자입니다 dc(역 폴란드 표기법).

$ base30_dc _1234
- 01 11 04
$ base30_dc '0 1234 -'
- 01 11 04

산술 표현식 내에서 인식되는 숫자 유형도 쉘마다 다릅니다.

1230123POSIX에서는 10진수, 8진수, 16진수 상수를 각각 인식하려면 최소한 및 구문이 필요합니다 0x123. 일부 쉘은 기본적으로 8진수를 선호 mksh하거나 zsh인식하지 않습니다 0123. 그렇게 하면 유용한 것보다 더 자주 방해가 되며(예: 0-패딩된 숫자를 처리할 때) 특정 POSIX 호환 모드가 활성화된 경우에만(옵션 posix또는 )의 시뮬레이션.mkshoctalzeroesshzsh

ksh, bash 및 zsh는 12#123모든 베이스의 입력 숫자에 대한 표현을 지원합니다(역시 범위는 서로 다릅니다).

2#111zsh는 이진수 교체로 0b111을 지원합니다. _가독성을 높이기 위해 내부 번호를 삽입합니다 (예: 1_000_000또는 0xdead_beef).

ksh93, zsh 및 yash는 부동 소수점 숫자( 0.123또는 0,123로케일에 따라 ksh93에서),,, 1e20...를 지원합니다. ksh93은 또한 0xA.Bp-3(또는 로케일에 따라 0xA,Bp-3)과 같은 16진수 부동 소수점 표현을 지원합니다.infnan

답변2

Bash(또는 실제로 다른 쉘)는 일반 프로그래밍에 적합한 도구가 아닙니다. Bash는 더 복잡한 연산은 커녕 부동 소수점 연산도 처리하지 않습니다. 껍질은껍데기, 그 안에 간단하고 작은 스크립트를 작성할 수 있지만 범용 프로그래밍 언어로 생각해서는 안 됩니다. 그렇지 않습니다.

이와 같은 작업을 수행하기 위해 bash를 사용해야 한다고 주장한다면 다음으로 시작하는 점점 더 복잡한 해결 방법을 사용해야 할 것입니다 printf.

$ printf '%x\n' "$((0xa+1))"
b

좋은 소식은 최소한 다음과 같은 작업을 수행할 수 있다는 것입니다.

$ printf '%x\n' 11
b

printf따라서 하나에서 다른 것으로 쉽게 변환할 수 있습니다. 즉, 매번 다음을 호출할 필요가 없습니다 .

var=0xa

((var++))
echo "Var (decimal): $var"
printf 'Var (hex): %x\n' "$var"

위 명령을 실행하면 다음이 인쇄됩니다.

$ foo.sh
Var (decimal): 11
Var (hex): b

즉, 16진수로 작업을 수행할 수 있으며 무언가를 인쇄해야 할 때까지 표시 방법에 신경 쓰지 않아도 됩니다.

하지만 아니요, 쉘에서 이와 같은 작업을 수행하는 기본 방법을 찾지 못할 것입니다. 왜냐하면 쉘을 설계된 목적 이외의 다른 용도로 사용하려고 하기 때문입니다.

관련 정보