2014-11-13 3 views
0

awk 프로그램 내에서, 나는 함께 실행되는 이진 문자열 집합을 생성하는 몇 가지 명령을 호출합니다. 각 문자열 내의스트림의 특정 오프셋에서 바이트를 편집하십시오.

:

  • 는 바이트로를 0x04 오프셋에서 시작
  • 네 바이트은 0x09는 문자열의 (리틀 엔디안) 길이 오프셋 타입 코드이다.

유형 코드가 0x20 인 경우이를 0x1E로 변경하고 싶습니다.

예 : 첫 번째 문자열의

처음 몇 바이트는 다음과 같습니다를 0x04 오프셋에서

4a d8 64 54 13 01 00 00 00 2d 00 00 00 

, 우리는 타입 코드는 0x13의입니다 참조, 그래서 아무것도하지 않습니다.

오프셋 0x09에서 우리는 길이가 2d 00 00 00임을 알 수 있습니다.이 문자열의 시작 부분부터 멀리 앞으로 이동하여 다음 문자열의 시작을 찾습니다.

다음 문자열을 시작합니다를 0x04 오프셋에서

4a d8 64 54 20 01 00 00 00 2c 00 00 00 

, 우리는 유형 코드가 0x20입니다 참조하십시오. 0x1E로 변경하십시오.

오프셋 0x09에서 우리는 길이가 2c 00 00 00임을 알 수 있습니다.이 문자열의 시작 부분부터 멀리 떨어져 다음 문자열 (또는 EOF)의 시작 부분을 찾으십시오.

어떤 유틸리티가 가장 적합합니까?

+2

나는 이것이 [tag : awk]의 작업이 아니라고 생각합니다. A [tag : perl]은 이것에 더 적당하다 ('pack()','unpack()'을 보라). – TrueY

+1

데이터를 구문 분석하여 예제로 표시 할 수 있습니까? 그런 다음'if ($ 4 == "20") ... 형식 테스트를 사용할 수 있습니다. ? 그러나'perl'은 학습 곡선을 가질 여유가 있다면 피할 수없는 향상이 필요할 때 더 좋아질 것으로 보인다. 행운을 빕니다. – shellter

+0

나는 약간 혼란 스럽다. 오프셋이 리틀 엔디안 인 경우 바이트가 '2d' '00' '00' '00'을 따라 상위 메모리 주소를 향하면 그 값은 0x2d000000이 아닌 0x2d입니다. – TrueY

답변

2

에서 솔루션을 구현했습니다. 나는 크기가 13 바이트 헤더를 포함하지 않는다고 가정한다. 그것은 완전히 깃털이 아니라 작동합니다. 워크 벤치 모델의 일종입니다. 메모리에 일부 데이터를 만든 다음 수정합니다.

그래서 처음 부분은 헤더에 따른 메모리의 데이터를 작성 <header1><zero data1><header2><zero data2> :

#!/usr/bin/perl 

use strict; 
use warnings; 

# Glues binary strings -> not needed $a.$b works properly 
#sub glue(@) { pack "W*", map { unpack("W*", $_) } @_; } 

# Creates a <header:null data> record 
sub pck(@) { 
    my $h = pack "(H[2])*", @_; 
    # If it is big-endian use N instead of V!!! 
    # It has to be unpacked to get the 32 bit data size 
    my @u = unpack "C5V2", $h; 
    my $b = pack "x$u[6]"; # put a lot of NULL bytes 

    $h.$b; 
} 

my @h1=qw(4a d8 64 54 13 01 00 00 00 2d 00 00 00); 
my @h2=qw(4a d8 64 54 20 01 00 00 00 2c 00 00 00); 
my $d1 = pck @h1; 
my $d2 = pck @h2; 
my $d = $d1.$d2; 

지금 $d 두 개의 레코드를 포함한다. 이제 우리는 데이터를 덤프 할 수 있습니다

sub dumpbin(@) { 
    open my $fh, "|od -t x1" or die; 
    binmode $fh; 
    print $fh @_; 
    close $fh; 
} 

dumpbin($d); 

출력 : 이제

0000000 4a d8 64 54 13 01 00 00 00 2d 00 00 00 00 00 00 
0000020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
* 
0000060 00 00 00 00 00 00 00 00 00 00 4a d8 64 54 20 01 
0000100 00 00 00 2c 00 00 00 00 00 00 00 00 00 00 00 00 
0000120 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
* 
0000160 00 00 00 
0000163 

필요한 경우 데이터, 분석 및 수정할 수 있습니다 인 - 메모리. 헤더가 덤프됩니다. 오프셋은 od의 출력과 일치하도록 8 진수로 인쇄됩니다.

print "=====\n"; 
for (my $offs=0; $offs<length($d);) { 
    # Unpack header 
    my @h = unpack "C5V2", substr($d, $offs, 13); 
    # Checks if the header type is 0x20 and modifies it 
    if ($h[4] eq 0x20) { substr($d, $offs + 4, 1) = pack "W", 0x1e;} 
    printf "%07o HDR: %s%s\n", $offs, join(" ", map {sprintf "%x", $_} @h), 
    $h[4] eq 0x20 ? " *" : ""; 
    $offs += 13 + $h[6]; 
} 
print "=====\n"; 

출력 (수정 라인 '*'로 표시) 우리 결과 덤프 경우가 알 수

===== 
0000000 HDR: 4a d8 64 54 13 1 2d 
0000072 HDR: 4a d8 64 54 20 1 2c * 
===== 

데이터가 정상적으로 변경되었는지 :

dumpbin($d); 

출력 :

0000000 4a d8 64 54 13 01 00 00 00 2d 00 00 00 00 00 00 
0000020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
* 
0000060 00 00 00 00 00 00 00 00 00 00 4a d8 64 54 1e 01 
0000100 00 00 00 2c 00 00 00 00 00 00 00 00 00 00 00 00 
0000120 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
* 
0000160 00 00 00 
0000163 

데이터가 수정되었음을 나타냅니다.

입력 파일이 크면 데이터를 청크로 읽고 수정하고 다시 쓸 때 약간의 코드가 필요합니다.

도움이 되었기를 바랍니다.

관련 문제