1. Diese Seite verwendet Cookies. Wenn du dich weiterhin auf dieser Seite aufhältst, akzeptierst du unseren Einsatz von Cookies. Weitere Informationen
  2. Unsere jährliche Weihnachts-Banner-Aktion hat begonnen! Wir freuen uns auf viele, viele kreative Vorschläge.
    Mehr dazu könnt Ihr hier nachlesen: Weihnachtsbanner 2016

    Information ausblenden

In einer binaeren Datei Positionen bestimmter Integer suchen?

Dieses Thema im Forum "Unix & Terminal" wurde erstellt von Walli, 21.05.07.

  1. Walli

    Walli Blutapfel

    Dabei seit:
    06.01.06
    Beiträge:
    2.594
    Hallo,

    Ich moechte in einer Binaerdatei, die einfach ein Array von 32-Bit Integern beinhaltet, nach Integern suchen, die kleiner als 0 sind und dazu die Positionen dieser Integer innerhalb der Datei wissen. Hat jemand eine Idee wie ich so etwas in einer Shell realisieren kann oder muss ich mir dafuer extra ein Programm basteln? Ich frage dies, weil ich oefters in binaeren Dateien suchen muss und da ganz unterschiedliche Sachen mache. Jedesmal ein extra Programm dafuer zu stricken, kompilieren usw. ist mir da auf Dauer zu nervig ;) .

    Danke fuer Tips,
    Walli
     
    #1 Walli, 21.05.07
    Zuletzt bearbeitet: 21.05.07
  2. quarx

    quarx Hadelner Sommerprinz

    Dabei seit:
    17.04.05
    Beiträge:
    8.541
    Code:
    man grep
     
  3. Trapper

    Trapper Boskop

    Dabei seit:
    12.05.05
    Beiträge:
    213
    @quarx: Ohne an den Fähigkeiten von grep zweifeln zu wollen, aber den Aufruf würde ich gerne sehen!
     
  4. quarx

    quarx Hadelner Sommerprinz

    Dabei seit:
    17.04.05
    Beiträge:
    8.541
    Nun denn. Habe mir zunächst mal eine Binärdatei aus den 5 Integern 2,1,0,-1 und -2 als Testkandidaten erzeugt. Die Datei ist 5*4=20 Bytes groß, die Integers sind im Big-Endian Format (d.h. hohe Bytes zuerst) abgelegt. Bei Intel-Macs wäre es wahrscheinlich genau andersrum. Im Hexeditor sieht die Datei also so aus:
    Code:
    00 00 00 02 00 00 00 01 00 00 00 00 FF FF FF FF FF FF FF FE
    Durch die Zweierkomplementdarstellung ist bei negativen Zahlen immer das höchste Bit belegt. Entspricht also einem der Fälle {8,9,A,B,C,D,E,F} für das höchste Nibble. Beim grepen müssen wir demnach jedes 8te Zeichen - beginnend mit dem ersten - auf den entsprechenden regulären Ausdruck testen.

    Jetzt der Trick: "hexdump" (oder auch "od") vorschalten zur Hexadezimal-Ausgabe der Binärdatei, versehen mit einer geeigneten Formatierung. Dann ist das Suchen ein Klacks:
    Code:
     hexdump -e'1/4 "%07_ax %08X\n"' binary.dat | grep ' [8-9A-F]'
    Hier wird die Binärdatei z.B. mit 7spaltiger hexadezimaler Adressangabe ausgegeben, pro Zeile 4 Bytes (d.h. 8 Nibbles). Suchen muss man dann nur noch nach Leerzeichen plus eins der Anfangsnibbles. Ausgabe von hexdump alleine:
    Code:
    0000000 00000002
    0000004 00000001
    0000008 00000000
    000000c FFFFFFFF
    0000010 FFFFFFFE
    und mit grep natürlich
    Code:
    000000c FFFFFFFF
    0000010 FFFFFFFE
    
    OK, die Hauptarbeit ist das Aufbereiten der Binärdaten mit dem Hexdump. :innocent:
     
    Trapper gefällt das.
  5. Walli

    Walli Blutapfel

    Dabei seit:
    06.01.06
    Beiträge:
    2.594
    Danke für die ausführliche Antwort. Auf die Lösung wäre ich jetzt nicht so schnell gekommen. Ich könnte mir zwar vorstellen, dass es durch den Umweg über den Hexdump bei großen Dateien etwas langsam sein könnte, aber ich probiere es später mal aus. :)
     
    #5 Walli, 22.05.07
    Zuletzt bearbeitet: 22.05.07
  6. Trapper

    Trapper Boskop

    Dabei seit:
    12.05.05
    Beiträge:
    213
    Danke, darauf wollte ich hinaus. Aber sehr kreativ gelöst! Das gibt Karma :)
     
  7. pi26

    pi26 Adams Parmäne

    Dabei seit:
    17.12.04
    Beiträge:
    1.297
    Hallo,

    eine Variante mittels Postscript (Programm als nur Text sichern und den Dateianhang ".ps" verwenden; dann mit dem Programm Vorschau öffnen).


    Code:
    
    /pfad (Users/DeinKurzname/Documents/BinaryfileTest.txt) def
    
    a4
    /x 30 def /y 800 def
    /str4 4 string def
    /Helvetica findfont 12 scalefont setfont
    
    x y moveto (Datei: ) show pfad show /y y 24 sub def
    x y moveto (An folgenden Indexes negative 32-Bitwerte gefunden:) show
    /y y 24 sub def
    
    /ausgabeindex 
    {
    y 30 lt {gsave showpage grestore /y 800 def} if
    i 10 string cvs x y moveto show 
    /y y 16 sub def
    }def
    
    
    /f pfad (r) file def
    /i 0 def
    {
    f str4 readstring {0 get 128 ge {ausgabeindex}if}{exit}ifelse
    /i i 1 add def
    }
    loop
    f closefile
    
    showpage
    
    mfg pi26
     
    Walli, quarx und (gelöschter Benutzer) gefällt das.
  8. quarx

    quarx Hadelner Sommerprinz

    Dabei seit:
    17.04.05
    Beiträge:
    8.541
    Das ist jetzt aber wirklich abgefahren, pi26! :cool:

    @Walli: Mit reinem Perl funktioniert es wahrscheinlich ohne Umweg über "hexdump". Das geht mir allerdings nicht so flüssig von der Hand... :eek:
     
  9. Walli

    Walli Blutapfel

    Dabei seit:
    06.01.06
    Beiträge:
    2.594
    Ja, hatte ich auch mal drüber nachgedacht. Das Problem mit Perl ist bei mir immer, dass ich meine eigenen Quelltexte nach 5 Minuten nicht mehr verstehe. Bin da auch nicht wirklich fit drin ;) .

    Die Postscript-Lösung ist echt mal freakig ;) . Danke!
     
    #9 Walli, 22.05.07
    Zuletzt bearbeitet: 22.05.07
  10. Walli

    Walli Blutapfel

    Dabei seit:
    06.01.06
    Beiträge:
    2.594
    Ich habe mich auch noch mal an Perl versucht. Hat jemand eventuell 'ne Idee, warum folgende Loesung nicht funktioniert?

    Code:
    #!/usr/bin/perl
    
    $file = $ARGV[0];
    $size = -s $file;
    
    open(FILE,"<$file") or die "Input file: Cannot open file\n\n";
    
    $i = 0;
    my $buffer;
    
    while($i < $size) {
    	read (FILE, $buffer, 4);
    	use integer;
    	if($buffer < 0) {
    		print $i.' '.$buffer."\n";
    	}
    	$i = $i+4;
    }
    
    close(FILE);
    
     
  11. quarx

    quarx Hadelner Sommerprinz

    Dabei seit:
    17.04.05
    Beiträge:
    8.541
    Naja, $buffer ist ja ein String, die Abfrage "$buffer<0" ist niemals wahr. Man muss die 4 Bytes "binär" in einen Integer umwandeln, z.B. mit
    Code:
    unpack("i",$buffer)
    (wie ich mir grad ergooglete). Dann klappt's wohl.
     
    Walli gefällt das.
  12. Walli

    Walli Blutapfel

    Dabei seit:
    06.01.06
    Beiträge:
    2.594
    Ah, das probiere ich aus. Wie gesagt... Perl ist nicht ganz mein Fall ;) . Danke!
     

Diese Seite empfehlen