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#BAD
077
8#77
octal_zeroes
zsh
또한 정수 산술 표현식( , , , , 등과 같은 산술 연산자 zsh
사용) 내에서 변수를 할당하면 정수 유형을 가져오고 (진이 할당되지 않은 경우) 명시적인 기수가 있는 가장 오른쪽 정수를 상속합니다. 상수의 기본(예 : , , )입니다.=
--
++
*=
-=
+=
10#12
0x12
0b11
예를 들어 . (( a = 0x10 + 0b1000 ))
는 값이 24인 정수 변수로 typeset -gi2 a=24
정의되고 이진수( )로 확장됩니다.a
$a
2#11000
info zsh 'Arithmetic Evaluation'
자세히보다.
bash
ksh에서는 복사 typeset -i
하지만 복사하지는 않습니다 typeset -i<base>
.
bash
숫자를 10이 아닌 진수 로 변환 하려면 printf
내장 함수를 사용하여 다른 사람들이 보여주듯이 8과 16을 나타내거나 ///를 사용하여 다른 진수(지원되는 진수의 범위와 그 진수의 범위)를 나타낼 수 있습니다 dc
. 표현된 것은 이러한 염기 간의 차이점))입니다.bc
ksh
zsh
예를 들어, 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
산술 표현식 내에서 인식되는 숫자 유형도 쉘마다 다릅니다.
123
0123
POSIX에서는 10진수, 8진수, 16진수 상수를 각각 인식하려면 최소한 및 구문이 필요합니다 0x123
. 일부 쉘은 기본적으로 8진수를 선호 mksh
하거나 zsh
인식하지 않습니다 0123
. 그렇게 하면 유용한 것보다 더 자주 방해가 되며(예: 0-패딩된 숫자를 처리할 때) 특정 POSIX 호환 모드가 활성화된 경우에만(옵션 posix
또는 )의 시뮬레이션.mksh
octalzeroes
sh
zsh
ksh, bash 및 zsh는 12#123
모든 베이스의 입력 숫자에 대한 표현을 지원합니다(역시 범위는 서로 다릅니다).
2#111
zsh는 이진수 교체로 0b111을 지원합니다. _
가독성을 높이기 위해 내부 번호를 삽입합니다 (예: 1_000_000
또는 0xdead_beef
).
ksh93, zsh 및 yash는 부동 소수점 숫자( 0.123
또는 0,123
로케일에 따라 ksh93에서),,, 1e20
...를 지원합니다. ksh93은 또한 0xA.Bp-3(또는 로케일에 따라 0xA,Bp-3)과 같은 16진수 부동 소수점 표현을 지원합니다.inf
nan
답변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진수로 작업을 수행할 수 있으며 무언가를 인쇄해야 할 때까지 표시 방법에 신경 쓰지 않아도 됩니다.
하지만 아니요, 쉘에서 이와 같은 작업을 수행하는 기본 방법을 찾지 못할 것입니다. 왜냐하면 쉘을 설계된 목적 이외의 다른 용도로 사용하려고 하기 때문입니다.