perl искать и удалять по разным смещениям в binmode

Это мой сценарий, который я пишу.

#usr/bin/perl
use warnings;


open(my $infile, '<', "./file1.bin") or die "Cannot open file1.bin: $!";
binmode($infile);
open(my $outfile, '>', "./extracted data without 00's.bin") or die "Cannot create extracted data without 00's.bin: $!";
binmode($outfile);

local $/; $infile = <STDIN>;
   print substr($infile, 0, 0x840, '');
   $infile =~ s/\0{16}//;
   print $outfile;

Я загружаю двоичный файл в Perl. Я мог искать и исправлять по определенным смещениям, но я хотел бы теперь найти любой экземпляр "00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00" (16 байт?) и удалить его из файла, но не менее 16 байт. . Что-нибудь меньшее, чем это, я хотел бы уйти. В некоторых файлах смещение, где начинаются 00, будет с другим смещением, но если я правильно думаю, если я могу просто найти 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 и удалить любой его экземпляр, тогда не будет иметь значения, какое смещение находится в 00. . Я бы сначала извлек данные из определенных смещений, затем искал файл и удалял из него 00-е. Я уже могу извлечь определенные смещения, которые мне нужны, мне просто нужно открыть извлеченный файл и сбрить 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00

EF 39 77 5B 14 9D E9 1E 94 A9 97 F2 6D E3 68 05
6F 7B 77 BB C4 99 67 B5 C9 71 12 30 9D ED 31 B6 
AB 1F 81 66 E1 DD 29 4E 71 8D 54 F5 6C C8 86 0D 
5B 72 AF A8 1F 26 DD 05 AF 78 13 EF A5 E0 76 BB 
8A 59 9B 20 C5 58 95 7C E0 DB 44 6A EC 7E D0 10 
09 42 B1 12 65 80 B3 EC 58 1A 2F 92 B9 32 D9 07 
96 DE 32 51 4B 5F 3B 50 9A D1 09 37 F4 6D 7C 01 
01 4A A4 24 04 DC 83 08 17 CB 34 2C E5 87 26 C1 
35 38 F4 C4 E4 78 FE FC A2 BE 99 48 C9 CA 69 90 
33 87 09 A8 27 BA 91 FC 4B 77 FA AB F5 1E 4E C0        I want to leave everything from
F2 78 6E 31 7D 16 3B 53 04 8A C1 A8 4B 70 39 22 <----- here up
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 <----- I want to prune everything
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00        from here on
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00<---- this IS the end of the file, and
                                                     just need to prune these few rows
                                                     of 00's

Скажем, что "F2 78 6E" из приведенного выше примера находится по смещению 0x45000 НО в другом файле 00 00 начинаются с другого смещения, как я могу закодировать это так, чтобы 00 00's было обрезано. В любом файле, который я открываю? Если мне нужно быть более конкретным, просто спросите. Похоже, я заглядывал в файл до тех пор, пока не наткнулся на длинную строку 00 00, а затем обрезал все оставшиеся строки. Это вообще имеет смысл? Все, что я хочу сделать, это найти в файле любые экземпляры 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 и удалить/обрезать/обрезать его. Я хочу сохранить все, кроме 00-х

EDIT #2 это сделало это:

open($infile, '<', './file1') or die "cannot open file1: $!";
binmode $infile;
open($outfile, '>', './file2') or die "cannot open file2: $!";
binmode $outfile;

local $/; $file = <$infile>;
$file =~ s/\0{16}//g;
print $outfile $file;


close ($infile);
close ($outfile);

Спасибо ikegami за вашу помощь и терпение :)


person james28909    schedule 09.02.2013    source источник
comment
Вы открыли $infile, но прочитали с STDIN. Вы перезаписываете дескриптор файла содержимым файла. (Показывает, что ваши имена переменных не соответствуют стандартам. Используйте ..._fh для дескрипторов файлов.) Вы не сказали, что печатать.   -  person ikegami    schedule 10.02.2013
comment
поверьте мне, я давал ему хороший ход человек. я думаю, что я собираюсь сдаться сегодня вечером и сделать еще немного завтра. спасибо за вашу помощь до сих пор. но чтобы было ясно, все, что я хочу сделать, это открыть извлеченный файл 59kn и удалить несколько строк 00; с конца, лол. звучит достаточно легко. Я могу открыть HxD и сделать это вручную, но хороший скрипт для двойного щелчка делает это намного проще для меня. я работаю с этими файлами ежедневно и должен проверять их вручную, и было бы неплохо иметь инструмент, который отделял бы каждую часть файла, файл 59 КБ - это только часть файла 16 МБ. но многие другие данные являются статическими,   -  person james28909    schedule 10.02.2013
comment
и у меня нет никаких проблем с извлечением этого, и то, что я делаю, - это извлечение чуть более 59 КБ, таким образом, каждый файл будет дополнен в конце 00-ми, тогда я хочу добавить этот скрипт, чтобы удалить их 00-е. в любом случае, спасибо за всю вашу помощь, чувак.   -  person james28909    schedule 10.02.2013


Ответы (1)


Нет такой вещи, как удаление из файла. Вы должны либо

  1. скопируйте файл без нежелательных битов или
  2. read остаток файла, seek назад, print ненужные биты, затем truncate файл.

Я пошел по варианту 1.

$ perl -e'
   binmode STDIN;
   binmode STDOUT;
   local $/; $file = <STDIN>;
   $file =~ s/\0{16}//;
   print $file;
' <file.in >file.out

Я загружаю весь файл в память. Любой из этих вариантов можно выполнять по частям, но это усложняет ситуацию, потому что ваши NUL могут занимать две части.


В плохо сформулированном обновлении вы, кажется, просили избегать изменений в первых байтах 0x840. Два решения:

$ perl -e'
   binmode STDIN;
   binmode STDOUT;
   local $/; $file = <STDIN>;
   substr($file, 0x840) =~ s/\0{16}//;
   print $file;
' <file.in >file.out

$ perl -e'
   binmode STDIN;
   binmode STDOUT;
   local $/; $file = <STDIN>;
   print substr($file, 0, 0x840, '');
   $file =~ s/\0{16}//;
   print $file;
' <file.in >file.out
person ikegami    schedule 09.02.2013
comment
Вы должны были сказать мне, почему мое решение было недостаточно хорошим. Я заметил ваше обновление только как случайность. - person ikegami; 10.02.2013
comment
исходный пост обновлен. когда я запускаю это, оно пытается запуститься, но зависает с мигающим курсором. - person james28909; 10.02.2013
comment
пожалуйста, имейте терпение со мной, это опыт обучения для меня. я могу программировать, но я не средний человек, так что, пожалуйста, наберитесь терпения;) я учусь, лол - person james28909; 10.02.2013
comment
могу ли я добавить этот файл только 59kb - person james28909; 10.02.2013
comment
смещения переменных не отличаются от файла к файлу не более чем на несколько килобайт. нет ли способа загрузить шестнадцатеричную строку, например, /0x00,/0x00,/0x00,/0x00,/0x00,/0x00,/0x00,/0x00,/0x00,/0x00,/0x00, /0x00,/0x00, /0x00, /0x00, /0x00 в переменную, а затем найти и удалить любые точные экземпляры этой точной переменной? тогда я мог бы просто извлечь нужный раздел и просто удалить шестнадцатеричные строки 00 с его конца, что не является 4 или 5 строками шестнадцатеричной строки. - person james28909; 10.02.2013
comment
Конечно, измените $file =~ s/\0{16}//; на $str = "\0" x 16; $file =~ s/\Q$str//; - person ikegami; 10.02.2013
comment
хорошо, у меня работает m8, но он удаляет только одну строку нулей - person james28909; 11.02.2013
comment
я устанавливаю тестовый файл с 5 строками 00 в шестнадцатеричном файле с именем file1, когда я запускаю его через cose, он удаляет одну строку 00. - person james28909; 11.02.2013
comment
мне просто нужно, чтобы он рекурсивно искал снова и снова, пока не сможет найти ни одного экземпляра 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 - person james28909; 11.02.2013
comment
кстати, спасибо за вашу помощь, человек, это действительно ценится. также это первый вариант, который у меня работает, просто нужно искать снова и снова. я бы использовал цикл своего рода? - person james28909; 11.02.2013
comment
о, вы хотите удалить все экземпляры 16 NUL? Добавьте флаг g к замене, s/\0{16}//g. - person ikegami; 11.02.2013
comment
не убивайте меня, но как бы я раздевал FF таким же образом? я пытался ввести $file =~ s/\F{16}//g; но это ничего не делает. - person james28909; 11.02.2013