Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Perl: Общие вопросы > Перемещение по файлу


Автор: bamper 18.6.2008, 18:20
Здравствуйте многоуважаемые.

У меня такой вот вопрос по работе с файлами. Я обрабатываю файл следующего содержания:

ISA00          0804041802U004030000038200P:  filename1.txt    28029
ISA01   097509996  6111492199200804041802
...............................................................................................
ISA00          0804041802U004030000038200P:  filename2.txt    28029
ISA01   097509996  6111492199200804041802
...............................................................................................

В файле есть повторяющиеся сегменты.  Я вытаскиваю имена файлов (filename1.txt, filename2.txt и т.д.) которые находятся на одинаковом байтовом смещении (по моему  smile  ) относительно начала строки с полем ISA. Считать первое поле зная значение смещения я могу: seek + read.  Но вот как перейти к следующему сегменту и считать следующий filename, - с этим у меня проблемы.

Обрабатываемый файл может достигать нескольких сотен мегабайт.

Автор: tolkien 18.6.2008, 19:17
Если размеры считываемых сегментов фиксированы seek+read. Если нет, то только последовательно просматривать каждую строку

Автор: ginnie 18.6.2008, 19:24
bamper, как вариант, сначала создать новый файл, содержащий только строки с ISA00 и его построчно обработать (поле выбирать путем split строки по пробельным символам).

Автор: bamper 18.6.2008, 19:51
Цитата(tolkien @ 18.6.2008,  19:17)
Если размеры считываемых сегментов фиксированы seek+read. Если нет, то только последовательно просматривать каждую строку

Нет. Сегменты не фиксированы по размеру. 

Автор: Itsys 18.6.2008, 19:58
А почему бы не воспользоваться регулярным выражением?

Автор: bamper 18.6.2008, 20:39
Цитата(Itsys @ 18.6.2008,  19:58)
А почему бы не воспользоваться регулярным выражением?

Можно с примером пожалуйста.

Воспользовавшись подсказкой ginnie я организовал все следующим образом:

Код

open F, "file.txt" or die "Can't $ARGV[0]$file";
my @lines = <F>;
foreach $lines(@lines) 
 {
 if (($lines =~ m/ISA00/) == 1) {
 #сохранение линии в файл и последующая обработка
 }
}


Хм... А как еще к этой строке две послеидущие добавить? Там тоже нужная информация оказалась.

Автор: amg 19.6.2008, 06:38
Цитата(bamper @  18.6.2008,  20:39 Найти цитируемый пост)
А как еще к этой строке две послеидущие добавить? 

Это легко (см. код ниже). Только не нужно зачитывать сразу весь большой файл в массив, памяти не хватит -- будет плохо. Лучше читать его построчно, можно тут же и обрабатывать найденные строки.
Код
open F, '<', "file.txt" or die "Can't open file.txt";
while (my $line = <F>) {
  if ($line =~ /^ISA00/) {
    my $line2 = <F> if ! eof;
    my $line3 = <F> if ! eof;
    # Обрабатываем $line, $line2, $line3
    print "1: $line 2: $line2 3: $line3"; 
  }
}
close F;


Автор: Bulat 19.6.2008, 11:38
bamper, ИМХО, проще применить на регулярные выражения. Только я не до конца понял, что именно Вам нужно получать из текущей строки smile

Автор: bamper 19.6.2008, 14:34
Цитата(Bulat @ 19.6.2008,  11:38)
bamper, ИМХО, проще применить на регулярные выражения. Только я не до конца понял, что именно Вам нужно получать из текущей строки smile

из строки я вытягиваю filename.txt. я просто split`ую строку я вытягиваю нужный мне аргумент. 

Автор: Bulat 19.6.2008, 14:47
Код

open(LOGFILE, "file.txt");
while (my $line = <LOGFILE>) {
  chomp($line);
  if ($line =~ /^.*?(filename\d+?\.txt).*?$/) {
    print $1, "\n"; 
  }
}
close(LOGFILE);

Автор: bamper 19.6.2008, 20:11
Спасибо за помощь!..  smile 

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)