Mam duży plik binarny (kilkaset GB) i chcę z niego wyodrębnić segment. Znam szesnastkowe ciągi początkowych i końcowych punktów.
Możliwe rozwiązanie (zakładając, że możesz zrobić kopię pliku) może skorzystać z następującego przykładu
tf
i ma długość 5000 bajtównastępnie
wykonaj kopię tf
nowego pliku blah
ze zmienionym wzorcem początkowym
$ LC_ALL=C sed 's/'`printf "\x4f\x0f\x87\x82"`'/'`printf "AAAA"`'/' <tf > blah
teraz znajdź lokalizację gdzie tf
i się blah
różnią ( uwaga - sed zapisuje dodatkowy bajt zawierający nowy wiersz na końcu zmodyfikowanego pliku, więc porównujemy do długości oryginalnego pliku tf
. Wygenerowany plik blah
powinien być o jeden bajt dłuższy ).
$ cmp -n 5000 -b tf blah
da to offset bajtowy, bs, gdzie pliki się różnią, np.
tf blah differ: byte 4337, line 10 is 117 O 101 A
teraz zrób to samo dla zakończenia wzoru
$ LC_ALL=C sed 's/'`printf "\xfb\x8c\xe2\xa0"`'/'`printf "AAAA"`'/' < tf > blah2
$ cmp -n 5000 -b tf blah2
tf blah2 differ: byte 4433, line 10 is 373 ? 101 A
teraz użyj, dd
aby wyodrębnić część zainteresowania
dd if=tf skip=4336 bs=1 count=100 > fbit
Kilka dodatkowych notatek:
niektóre wersje sed obsługują -b
opcję, która traktuje plik wejściowy jako binarny. Inne wersje mają -z
opcję oddzielającą wiersze znakami NUL. W obu przypadkach pasujące wzorce zawierające nową linię lub podział na nową linię nie zostały przetestowane.
count=100
zależy od długości wzoru dopasowane i czy dopasowanym wzorcem być zawarte w wyciągu (nie był jasny w tej kwestii). Ogólna formuła to liczba = (przesunięcie końcowe) - (przesunięcie początkowe) + (rozmiar wzoru końcowego) . Fragmenty dla konkretnego przykładu to 4433-4337 + 1, co daje 97 bajtów. To jest od początku wzorca początkowego do pierwszego bajtu wzorca końcowego włącznie. Dodatkowe 3 bajty są następnie dodawane, aby dać 100 w tym przykładzie, ponieważ końcowy wzorzec miał cztery bajty, a przykład zawiera końcowy wzorzec. Jeśli końcowy wzorzec nie był pożądany, count=96
byłaby to wartość.
możliwe jest podejście bardziej odporne na nowe linie i użycie polecenia hexdump. Nie w pełni przetestowałem to podejście. Zasadniczo użyłby hexdump z odrobiną sed, grep i tr, aby przekonwertować oryginalny plik binarny na hex w formie ascii. Wtedy można zastosować ten sam proces, ale z bardziej skomplikowaną arytmetyką itp. Potrzebne byłoby polecenie hexdump
hexdump -v -x tf | sed s/'^[0-9]*\(.*\)/\1/' | sed s'/ *//g' | grep '[0-9]' | tr -d '\n' > tf.txt
Po hexdump
etapie można zastosować ten sam proces sed
i cmp
. Dopasowany wzorzec musiałby zostać zaktualizowany, aby używać znaków ascii w postaci zrzutu heksowego, a nie surowego wydruku szesnastkowego.
To podejście powinno także obsługiwać znaki nowego wiersza.
LC_ALL=C
wydaje się być domyślnie potrzebny w OSX. Bez tego sed
polecenie powoduje błąd RE error: illegal byte sequence
. Może nie być to prawdą na wszystkich platformach i / lub dystrybucjach systemów operacyjnych.
96
? (Wskazówka: Pomyśl o tym. Wierzę, że to źle.) (2) To nie zadziała, jeśli jednym ze znanych bajtów jest hex0A
. Czy potrafisz rozszerzyć swoją odpowiedź na tę sprawę? (3) Czy jestLC_ALL=C
potrzebny? Czy możesz mi wytłumaczyć dlaczego? (4) Podobnie, czy możesz wyjaśnić, dlaczego-n 5000
jest potrzebny? (5) Proszę zbadać „UUOC”. …………………………………………………………………………………………… Proszę nie odpowiadać w komentarzach; edytuj swoją odpowiedź, aby była jaśniejsza i bardziej kompletna.98
myliłem (to96
była literówka). Jest tak, ponieważ twoja odpowiedź pokazuje przykładowy wzorzec końcowy, który ma cztery bajty. W przeciwnym razie dobra robota.