1

因此,我正在阅读日历文件以将日期插入文件中,并且我希望日期保持按时间顺序排列。当我找到日期应该去的地方时,问题就来了,文件已经越过了我想要插入的点。

我正在查看的日历文件如下所示:

# 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

4 回答 4

6

您需要在文件中随机移动的功能是seek。但是在 Perl 常见问题解答中有更多关于如何解决这个问题的信息 -如何在文件中更改、删除或插入一行,或附加到文件的开头?

于 2011-08-02T12:19:30.497 回答
3

这听起来对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 ) {
    ...
}
于 2011-08-02T12:37:15.007 回答
2

seek and tell将解决回绕的问题。您最终将覆盖当前存在的行。懒惰的解决方案是使用Tie::File,另一种可能是在写出新版本的同时读取文件,然后在完成后用新版本替换旧版本。

于 2011-08-02T12:20:14.600 回答
0

标准的 perl 解决方案是在问题上抛出内存:

打开(我的 $FILE,....);#以读/写模式打开
我的@lines = <文件>; #slurp 在文件的所有行中
...插入(或删除?)到数组中...
截断($文件,0);#如果删除,则需要截断
寻求($文件,0,0);
打印 $FILE @lines;

为了提高效率,您可以只从变化的角度而不是从所有内容开始编写,但如果速度不重要,那么简单性就具有较少的错误可能性。

于 2011-08-02T11:30:47.527 回答