hexdump
특히 사용자 정의 형식을 정의할 수 있기 때문에 정말 마음에 듭니다 .
$ echo -e '\x00\x01\x02\x03' | hexdump -v -e '1/1 "%_ad: "' -e '4/1 "%02X "' -e '1/1 " : "' -e '4/1 "%_p"' -e '1/1 "\n"'
0: 00 01 02 03 : ....
4: 0A : .
따라서 한 줄에 4바이트를 선택하고 먼저 16진수로 쓴 다음 문자로 쓸 수 있습니다. 그러나 여기서 누락된 것은 "이진 문자열"(또는 "비트 문자열") 형식 지정 문자입니다. 예 -e '4/1 "%08b "'
를 들어 명령줄 어딘가에 무언가를 쓰고 싶습니다 .
0: 00 01 02 03 : 00000000 00000001 00000010 00000011 : ....
4: 0A : 00001010 : .
물론 엔디안(1바이트 이상의 그룹을 형식화해야 하는 경우) 등을 지정해야 할 수도 있습니다. 그러나 어쨌든 매뉴얼에서 볼 수 있는 한 그러한 형식은 hexdump
존재하지 않습니다.
그래서 내 질문은 - 위의 바이너리 문자열을 포함하지만 해당 옵션을 사용할 때 프로그램의 사용자 정의 가능성을 최대 범위 hexdump
(바이트 그룹화 측면에서) 로 유지하는 형식화된 덤프를 얻을 수 있도록 Linux 명령줄에 어떤 대안이 있습니까 -e
?
답변1
덤프 프로그램이 적절한 덤프 옵션과 함께 작동하지 않는 경우에는 둘 다 사용한 다음 붙여넣기를 사용하여 출력을 결합하여 언제든지 함께 조각을 낼 수 hexdump
있습니다 xdd
. 예쁘지는 않지만 프로세스 대체를 지원하는 쉘을 사용하면 됩니다( bash
괜찮을 것입니다).
mkfifo fifo
echo -e '\x00\x01\x02\x03' |
tee fifo |
paste -d' ' \
<(hexdump -v -e '1/1 "%_ad: "' -e '4/1 "%02X "' -e '1/1 " :\n"') \
<(xxd -b -c 4 fifo | cut -d' ' -f 2-)
산출:
0: 00 01 02 03 : 00000000 00000001 00000010 00000011 ....
4: 0A : 00001010 .
답변2
pack()
이것은 / 함수 형식 지정자를 활용 하여 Perl을 사용하기 위한 나의 제안입니다 unpack()
. 테스트 호출은 다음과 같습니다.
$ echo -e '\x00\x01\x02\x03' | perl hexdump-00.pl --offset 120 --group 4 --add '(H2)*' --add '(B8)*'
Opening '' STDIN
Cannot seek!
0
00000000: 00 01 02 03 00000000 00000001 00000010 00000011 '....'
00000004: 0a 00001010 '.'
중간에 문자열 마커를 삽입하는 것은 조금 더 어렵습니다. 하지만 여전히 거기에 바이트를 "그룹화"할 수 있다는 이점이 있습니다. 예를 들어 다음과 같이 두 바이트를 그룹화하고 부호 있는(짧은) 정수로 해석할 수 있습니다.
$ perl -e 'print pack("s*\n", (-124))' | hexdump -C
00000000 84 ff |..|
00000002
$ echo -e '\x00\x01\x84\xff' | perl hexdump.pl \
--offset 120 --group 4 \
--add '(H2)*' \
--add '(B8)*' \
--add '(s2)*'
Opening '' STDIN
Cannot seek!
0
00000000: 00 01 84 ff 00000000 00000001 10000100 11111111 256 -124 '....'
00000004: 0a 00001010 '.'
이것은 hexdump-00.pl
:
#!/usr/bin/perl
# perl hexdump-00.pl --offset 120 --group 4 --add '(H2)*' --add '(B8)*' test.file
use strict;
use warnings;
use Getopt::Long;
use Fcntl qw(SEEK_CUR SEEK_SET);
my $offset = 0;
my $groupsize = 1;
my $length = 128;
my @list=();
my $result = GetOptions (
"offset=i" => \$offset,
"group=i" => \$groupsize,
"length=i" => \$length,
"add=s" => \@list,
);
my $inputfname="";
my $inputfh;
$inputfname = $ARGV[0] if defined $ARGV[0];
if (($inputfname eq "") || ($inputfname eq "-")) {
printf(STDERR "Opening '%s' STDIN\n", $inputfname);
$inputfh = *STDIN;
} else {
printf(STDERR "Opening '%s'\n", $inputfname);
open ($inputfh, "<$inputfname");
}
binmode($inputfh);
my $startaddr=0;
if( not(defined($startaddr = sysseek($inputfh, $offset-1, SEEK_SET))) ) {
printf(STDERR "Cannot seek!\n");
#~ $startaddr = sysseek($inputfh, 0, 0); // cannot reset like this
$startaddr = 0; # just avoid errors
}
print(STDERR $startaddr . "\n");
my $buffer=undef;
my $nread;
my $total=0;
while (($nread=sysread($inputfh, $buffer, $groupsize)) > 0) { # , $startaddr
#~ printf("%08X: nr: %d, buf '%s'\n",$startaddr,$nread,$buffer);
printf("%08X: ", $startaddr);
foreach my $tformat (@list) {
foreach my $tentry (unpack($tformat, $buffer)) {
printf("%s ", $tentry);
}
}
(my $newbuf = $buffer) =~ s/[^[:print:]]/./g; # make non-printable into '.'
printf(" '%s'", $newbuf);
print("\n");
$startaddr += $nread;
$total += $nread;
if ($total > $length) { last; }
}
close($inputfh);
답변3
출력을 베이스 2로 변환하기 위해 sed
수행할 수 있는 몇 가지 작업은 다음과 같습니다 .dc
od
od -t d1z -w4 -v -N12 </dev/urandom |
sed -e '1i2o' -e 's/.*/[&]p/p;$d
s/>/]n [>/;s/[^ ]*/&]n [/;h;s/>.*//;
s/ -/ _/g;s/ [^] [][^ ]*/ ]n&n [ /g;G
s/\n[^>]*//' |
dc
이제는 조금 더 쉬워졌습니다. 더 빨라졌다는 것은 말할 것도 없고요. 하지만 여전히 뷰티 퀸은 아닙니다. 또한 모든 바이트의 10진수와 밑이 2인 값을 인쇄합니다.
내가 그것을 실행하면 나는 얻는다 :
0000000 -43 125 -117 -39 >.}..<
0000000 -101011 1111101 -1110101 -100111 >.}..<
0000004 62 28 80 61 >>.P=<
0000004 111110 11100 1010000 111101 >>.P=<
0000010 6 14 120 -16 >..x.<
0000010 110 1110 1111000 -10000 >..x.<
0000014
또는...
echo aBcD | od -t d1z -w4 -v | sed ... | dc
0000000 97 66 99 68 >aBcD<
0000000 1100001 1000010 1100011 1000100 >aBcD<
0000004 10 >.<
0000004 1010 >.<
0000005
필드 너비에는 약간의 작업이 필요할 수 있지만 모두 귀하의 것입니다. 이 옵션은 필요하지 않습니다 -N12
. 저는 단지 의사 무작위 데이터의 끝없는 흐름에 질식하지 않기 위해 이 옵션을 사용합니다. 한 줄에 4바이트를 지정 하지만 -w4
어떤 숫자든 사용할 수 있어야 합니다. 또한 이 1i2o
sed
명령은 dc
출력의 기본( 2
이진수)에만 적용되지만 2에서 16 사이의 모든 기본이 제대로 작동합니다. 예를 들어, 16진수 및 2진법으로 출력을 보려면 첫 번째 sed
명령문에 "16i"를 추가하고 od
옵션을 -t d1z
로 변경합니다 t x1z
.
다른 옵션은 다음과 같습니다...
printf는 다음을 수행합니다.
printf '%o\n%x\n' 128 128
200
80
...심지어...
printf '%o\n%x\n' "'a" "'a"
141
61
바이너리에서는 그렇게 간단하지 않지만 사양에 맞게 설정하면 bc
모두 가능합니다.obase=
printf 'obase=2;%d
obase=8;%d
obase=16;%d
obase=2;%d
' 64 128 "'A" "'a" |
bc
산출
1000000
200
41
1100001
dc
별로 수다스럽지 않음:
printf '%do%dn10P' 2 64 8 128 16 "'A" 2 "'a" |dc
산출
1000000
200
41
1100001
더 많은 정보를 얻으세요 man dc bc
.
다시 말하지만, 파일 스트림의 경우 언제든지 다음을 사용할 수 있습니다 od
.
for o in o d x ; do
echo aBcD |
od -A n -t ${o}1z -v -w4
done
산출
141 102 143 104 >aBcD<
012 >.<
97 66 99 68 >aBcD<
10 >.<
61 42 63 44 >aBcD<
0a >.<
그리고^그거^od
오프셋을 인쇄하지 말라고 들었습니다 . 지금 추측하고 있습니다. -t
ype o
또는 한 번에 한 바이트 d
씩 출력하고 싶고 각 바이트의 ASCII 표현이 줄 끝에 추가 x
되기를 원합니다 .z
-v
(그래서 그것은 단지 나를 인쇄하지 않습니다 0*
for 0000
)라인당 바이트 수입니다 -w4
.
그렇지 않은 경우 -A n
다음과 같이 인쇄됩니다.
0000000 141 102 143 104 >aBcD<
0000004 012 >.<
0000005
0000000 97 66 99 68 >aBcD<
0000004 10 >.<
0000005
0000000 61 42 63 44 >aBcD<
0000004 0a >.<
0000005
물론 에서는 어떤 조합이라도 dc
bc
od
가능합니다 |pipeline
.