Как манипулировать указателем файла в Perl
Поэтому я читаю файл календаря, чтобы вставить дату в файл, и я хочу, чтобы даты оставались в хронологическом порядке. Проблема возникает, когда я нахожу место, куда должна идти дата, файл уже просматривает точку, в которую я хочу вставить.
Файл календаря, на который я смотрю, выглядит так:
# November 2010
11/26/2010
11/27/2010
11/28/2010
11/29/2010
11/30/2010
# December
12/24/2010
12/25/2010
12/26/2010
12/27/2010
12/28/2010
12/29/2010
12/30/2010
и мой код выглядит так:
while (my $line = <FILE>) {
if (substr($line, 0, 1) =~ m/\#/ || $line =~ m/calendar/) { #if the line is commented out or contains the calendar's name skip to next line
next;
}
chomp($line);
my ($temp_month, $temp_day, $temp_year) = split(/\//, $line, 3);
if ($year == $temp_year && $month == $temp_month && $day < $temp_day) {
?
}
}
Так есть ли какие-либо предложения относительно того, как указать на предыдущее место в файле?
4 ответа
Функция, которая вам нужна для случайного перемещения по файлу - это поиск. Но есть больше информации о том, как решить эту проблему в Perl FAQ - Как мне изменить, удалить или вставить строку в файл или добавить в начало файла?
Это звучит как отличное применение для модуля Tie::File. Вы можете обрабатывать файл как массив и не беспокоиться о текущей позиции указателя файла. Это также не зависит от загрузки всего файла в память - поэтому оно будет работать с массивными файлами.
use Tie::File;
tie @array, 'Tie::File', $file;
for (my $i =0; $i <= @array; $i++) {
if (/date comparison/*see note below) {
splice @array, $i, 0, $new_date;
}
}
Это позволит вам использовать функции массива perl, например, splice, для вставки новых строк.
Но у вас также есть большая проблема с вашей стратегией сравнения дат. Что, если в файле еще нет дат для данного месяца, года? Вы пройдете через и не найдете для этого места. Проверьте timelocal, который вы можете использовать, чтобы преобразовать обе даты в время эпохи, а затем сравнить их.
use Time::Local;
my $temp_epoch = timelocal(0,0,0,$temp_day,$temp_month -1, $temp_year-1900);
if ($epoch < $temp_epoch ) {
...
}
искать и рассказать решит проблему сворачивания назад. В итоге вы перезапишете существующие строки. Ленивое решение состоит в том, чтобы использовать Tie:: File, еще одну возможность - прочитать файл во время записи новой версии, а затем заменить старую версию новой, когда вы закончите.
Стандартное решение perl - бросить память на проблему:
открыть (мой $FILE, ....); # открыть в режиме чтения / записи my @lines =; #slurp во всех строках файла... вставить (или удалить?) в массив... усечь ( $FILE, 0); # при удалении вам нужно будет обрезать искать ( $FILE, 0, 0); выведите $FILE @lines;
Чтобы быть более эффективным, вы могли бы просто писать с точки изменения, а не со всего, но если скорость не важна, простота имеет меньший потенциал ошибок.