나는 awk
텍스트 파일을 구문 분석하는 데 사용합니다. 텍스트 파일에는 다음과 같은 4바이트 데이터 필드가 있습니다.
11110000 10100000 10110000 10010000
이 필드를 읽고 이진수에서 16진수로 변환하고 싶습니다. 현재 저는 10진수가 printf %x
되고 11110000
16진수가 됩니다. 이것이 나타내는 값은 1111000
가 0xA98760
아닙니다 0xF0
.
내 코드는 간단하고 BASH와 Linux를 처음 사용합니다.
awk'{printf(%x %x %x %x, $1, $2, $3, $4)};
문자열 필드를 바이너리로 저장한 다음 16진수로 변환하는 방법은 무엇입니까? "bc <<<"obase=16;ibase=2;를 사용하여 터미널에서 16진수를 얻을 수 있습니다. $변수"". 이 스크립트를 작성하려고 하면 구문 오류가 발생합니다.
답변1
awk
10진수, 8진수, 16진수만 지원되며, 2진수는 지원되지 않습니다. 당신이 사용할 수있는 perl
:
perl -lane 'BEGIN{$, = " "} print unpack "(H2)*", pack("(B8)4", @F)'
dc
GNU 의 경우 tac
(일부 시스템도 참조 tail -r
):
{ echo 16o2i; cat; echo f; } < file.txt | dc | tac
사용 (구문 오류가 bc
// / 의 최신 버전이 아닌 셸에서 사용된 연산자와 관련이 있다고 가정)<<<
zsh
zsh
bash
ksh93
mksh
yash
{ echo 'obase=16; ibase=2'; tr -cs 01 '[\n*]'; } < file.txt | bc
답변2
이것은 우아하지 않은 해킹이지만 작동합니다. 숫자의 이진 표현을 취하고 십진수 값을 반환하는 함수 b를 선언합니다. 그런 다음 %x를 사용하여 printf
16진수로 표시됩니다.
$ awk 'func b(i, t,a,c){a=1;for(c=length(i);c>0;c--){t+=substr(i,c,1)=="1"?a:0;a*=2}return t}{printf "0x%x 0x%x 0x%x 0x%x\n",b($1),b($2),b($3),b($4)}' bin.txt
0xf0 0xa0 0xb0 0x90
답변3
perl -pale '$_ = join $", map { sprintf "%X", oct "0b$_" } @F'
간단히:
Perl options: -p => autoprint + implcit file read in/line, a.la., awk -a => autosplit line into fields using default delimiter ' ' -l => ORS=IRS="\n" Perl standard variables: $" => list separator, by default it is a single space " " $_ => refers to the whole line, equivalent to $0 in awk @F => fields got by splitting the current line, $1, $2,$3, ... $NF in awk Perl code: map { body } list_of_items Map takes in an input list and applies the code present in it's body on each element of this list to generate an output list.
join <separator>, <list>
Join takes in an input list and joins their elements by the
separator provided in the first argument.
oct <number>
When the input to this function is prefixed by a "0b", then
it is treated to be a binary number and outputs the decimal
equivalent.
sprintf "%x" <decimal>
This function whose format is "%x" treats the input as
decimal and returns the equivalent number in hex.
답변4
대상 시스템에 GNU Bash가 있는 경우 산술 표현식에서 8진수 및 16진수 이외의 진수에 대한 지원을 활용할 수 있습니다. 예를 들어:
bash$ echo $(( 2#1011 | 2#1100 )) # bitwise OR of 11 and 12
15
좋아요, 이 데이터를 얻으면:
11110000 10100000 10110000 10010000
그리고 어떻게든 이 문법에 맞춰서 평가해 보세요.
$(( 2#11110000101000001011000010010000 ))
우리는 가치를 얻었습니다
4037062800
(예, 이는 32비트 bash 버전에서 작동하며 부정적인 결과를 얻지 못합니다.)
우리는 이것을 아주 간단하게 할 수 있습니다:
echo $(( 2#$(tr -d ' ' < file) ))
4037062800
유일한 문제는 모든 것이 eval
어떤 방식으로든 위장되어 있다는 것입니다. 파일 내용을 기반으로 명령의 출력을 표현식에 삽입한 다음 평가합니다. file
신뢰할 수 없는 출처에서 얻은 경우 보안 위험이 있을 수 있습니다. 예를 들어, 나는 file
인터넷 사용자가 제출한 양식의 POST 데이터를 포함하는 Apache의 CGI 스크립트에 이를 넣지 않을 것입니다 .