16진수 숫자가 상대적으로 작을 때 다음을 사용할 수 있습니다.
echo 0xFF| mawk '{ printf "%d\n", $1}'
16진수를 10진수로 변환합니다.
16진수 숫자가 매우 큰 경우 mawk
더 이상 작동하지 않습니다.
echo 0x8110D248 | mawk '{ printf "%d\n", $1 }'
출력 2147483647
(잘못된 것과 2147483647
동일함 0x7FFFFFFF
).
더 큰 숫자를 변환하는 방법은 무엇입니까?
처리해야 할 숫자가 너무 많습니다(한 줄에 하나의 숫자, 10M 이상). 예를 들어, 0xFF\n 0x1A\n 0x25\n
이 경우 어떻게 처리할 수 있나요? 통과 xargs
? 더 좋은 방법이 있나요? xargs
정말 느립니다.
답변1
임의로 큰 숫자에 대한 더 나은 명령은 입니다 bc
. 변환을 수행하는 기능입니다.
hextodec() {
local hex="${1#0x}"
printf "ibase=16; %s\n" "${hex^^}" | bc
}
hextodec 0x8110D248
2165363272
여기서는 변수를 사용할 때 변수 값을 조작하는 이상해 보이는 기능을 사용하고 있습니다.
"${1#0x}"
-"$1"
예상한 대로 이는 함수의 첫 번째 매개변수를 참조합니다.#
수정자 입니다 (man bash
예: 참조 또는 읽기POSIX) 값 앞부분에서 다음 표현식을 제거합니다. 예를 들어,0xab12
이는 다음과 같이 반환됩니다.ab12
"${hex^^}"
-"$hex"
알파벳 문자가 대문자로 매핑된 값을 참조하지만 반환합니다. (이것은bash
확장이므로 읽되man bash
POSIX는 읽지 마십시오.) 예를 들어 다음12ab34
과 같이 반환됩니다.12AB34
두 경우 모두 { … }
중괄호는 수정자를 변수에 바인딩합니다. 변수의 값만 반환되고 그 뒤에 두 개의 위쪽 화살표/캐럿 문자가 옵니다 "$hex^^"
.$hex
답변2
mawk
문제는 내부적으로 부호 있는 32비트 정수를 사용하므로 2 31 -1(즉, 2147483647)보다 큰 정수를 나타낼 수 없다는 사실에서 비롯됩니다 .
모든 크기의 16진수 파일을 스트리밍하려면 각 파일을 10진수로 변환하세요.
{
echo 'ibase=16'
sed -e 'y/xabcdef/XABCDEF/' -e 's/^0X//'
} | bc
먼저 ibase=16
로 전송되어 bc
유틸리티에 16진수를 읽도록 지시합니다. 그런 다음 16진수 문자를 대문자로 변환하고 파일에서 숫자의 접두사를 sed
제거하는 데 사용됩니다 . 접두사가 없고 대문자가 있는 16진수가 0x
필요하기 때문에 이렇게 합니다 .bc
0x
file
콘텐츠가 포함된 파일이 주어지면
0xFF
0x1A
0x25
0x7FFFFFFF
0x8110D248
0x8110D2487FFFFFFF
...파이프가 출력됩니다
255
26
37
2147483647
2165363272
9300164439347036159
파이프를 일반 스트림 셸 함수로 다시 작성할 수도 있습니다.
hex2dec () {
{ echo 'ibase=16'; sed -e 'y/xabcdef/XABCDEF/' -e 's/^0X//'; } | bc
}
hex2dec <file
# Or...
some-process-producing-data |
some-filter-extracting-hexadecimal-numbers |
hex2dec |
while IFS= read -r number
# use the decimal number in "$number" here.
done
답변3
@Stephane Chazelas가 제안한 대로 perl의 hex() 내장 함수를 사용하여 bignum 모듈을 사용하여 16진수->10진수 변환을 수행할 수 있습니다.
$ perl -Mbignum -lpe '$_=hex' file
모든 16진수 앞에 0x 또는 0X가 붙는 경우 내장된 8진수를 사용할 수도 있습니다.
$ perl -Mbignum -lpe '$_=oct' file
파일에서 데이터를 읽을 수 있는 GNU dc 데스크탑 계산기를 사용할 수 있습니다. 그러나 dc를 호출하기 전에 dc에서 요구하는 대로 대문자 16진수 표기법으로 전환하고 16진수 문자열에서 선행 0x를 제거합니다. 그런 다음 입력 기수를 16(16i)으로 설정하고 숫자만 인쇄합니다(기본값은 10입니다).
< file \
tr a-fx A-FX |
cut -d "X" -f 2 |
dc -e "16i [q]sq
[?z0=qpcz0=?]s?
l?x
"
16을 두 번째 인수로 사용하는 int() 내장 함수를 사용하면 첫 번째 인수인 16진수 문자열을 해당하는 10진수로 변환합니다.
python3 -c 'import sys
with open(sys.argv[1]) as f:
for l in f:
print(int(l.strip(),16))
' file
답변4
성명서에 대하여
mawk
...따라서 2^31-1보다 큰 정수(예: 2147483647)를 나타내지 않습니다.
존재하다@그들의 답변: 이 말은 틀렸습니다. 배정밀도 부호 없는 정수 제한인 2 53 -1 까지 16진수를 읽고 인쇄할 수 있습니다.
echo '0x1234BEEF9CAFE7' \
\
| mawk '{ CONVFMT=OFMT="%.20g";
print a=+( substr($0,1,length($0)-8)),\
b=+(("0x")(substr($0,1+length($0)-8))),\
c=2^32*a+b,\
sprintf("0x%X%.8X",a,b) }'
1193150 4020023271 5124544249245671 0x1234BEEF9CAFE7
또는 더 안전한 방법 - 높은 쪽을 16 7 로, 낮은 쪽을 16 6 으로 나누는 것입니다 .
echo '0x1234BEEF9CAFE7' | mawk '{ CONVFMT=OFMT="%.20g"; OFS="\f"; n=length(x=$0)
print a=+( substr(x,1,n-6)),
b=+(("0x")(substr(x,1+n-6))),
c=2^24*a+b,
sprintf("0x%X%.6X",a,b) }'
305446639
10268647
5124544249245671
0x1234BEEF9CAFE7
ndigits
다음은 원하는 16진수 숫자의 하한값을 얻기 위해 매개변수를 간단히 조정할 수 있는 보다 일반적인 버전입니다 .
echo '0x1234BEEF9CAFE7' \
\
| mawk '{ CONVFMT=OFMT="%.20g";
OFS="\f";
w=length(x=$0); ndigits=7; # enter 6, 7, or 8
print a=+( substr(x,1,w-ndigits)),
b=+(("0x")(substr(x,1+w-ndigits))),
c=(16^ndigits)*a+b,
sprintf("0x%X%.*X",a,ndigits,b) }'
19090414
261926887
5124544249245671
0x1234BEEF9CAFE7
10M 회선은 빨라야 합니다. 나는 5,578만 줄의 16진수를 포함하는 임의의 테스트 파일을 만들었습니다. 각 줄은 13개의 16진수로 구성됩니다.
% echo; ( time ( pvE0 < test_hex_list_01.txt| mawk 'BEGIN { CONVFMT=OFMT="%.20g"; const16=16^(ndigits=7) } { printf("%.f\n",const16*(a=+substr(x=$0,1,(w=length(x))-ndigits))+(b=+("0x"substr(x,1+w-ndigits))),a,ndigits,b) }' )) | pvE9 > test_hex_list_01_output_mawk_short.txt ; echo
out9: 2.22MiB 0:00:00 [22.1MiB/s] [22.1MiB/s] [<=> ]
in0: 851MiB 0:00:39 [21.5MiB/s] [21.5MiB/s] [=================>] 100%
out9: 887MiB 0:00:39 [22.6MiB/s] [22.4MiB/s] [ <=> ]
( pvE 0.1 in0 < test_hex_list_01.txt | mawk ; ) 39.20s user 0.94s system 101% cpu 39.64 out9: 887MiB 0:00:39 [22.4MiB/s] [22.4MiB/s] [ <=> ]
% awkwc5 < test_hex_list_01.txt
rows = 55,779,444. | UTF8 chars = 892,471,099. | bytes = 892,471,099.
약 5,600만 줄의 16진수를 완성하는 데 단 39.2초가 걸렸습니다.