读取和写入perl中的文件

时间:2012-09-28 04:50:05

标签: perl file-io

    this
    is just
    an example.

让我们假设上面是 out.txt 。我想阅读 out.txt 并写入同一个文件。

    <Hi >
    <this>
    <is just>
    <an example.>

修改 out.txt 。 我想在某些行的开头和结尾添加标签。 由于我将多次阅读该文件,因此每次都无法将其写入不同的文件。

编辑1 我尝试使用"+<",但它给出了这样的输出:

Hi
this
is just
an example.
<Hi >
<this>
<is just>
<an example.>
 **out.txt**

编辑2  代码参考:

open(my $fh, "+<", "out.txt");# or die "cannot open < C:\Users\daanishs\workspace\CCoverage\out.txt: $!";
     while(<$fh>)
     {
        $s1 = "<";
        $s2 = $_;
        $s3 = ">";
        $str = $s1 . $s2 . $s3;
        print $fh "$str";
     }

5 个答案:

答案 0 :(得分:7)

你想要做的事情的想法是有缺陷的。该文件以

开头
H  i  /  t  h  i  s  /  ...

如果您要更改它,在处理完第一行后会看起来如下:

<  H  i  >  /  i  s  /  ...

请注意你是如何破坏“th”的?您需要制作文件的副本,修改副本,用副本替换原件。

最简单的方法是在内存中制作此副本。

my $file;
{ # Read the file
   open(my $fh, '<', $qfn)
      or die "Can't open \"$qfn\": $!\n";
   local $/;
   $file = <$fh>;
}

# Change the file
$file =~ s/^(.*)\n/<$1>\n/mg;

{ # Save the changes
   open(my $fh, '>', $qfn)
      or die "Can't create \"$qfn\": $!\n";
   print($fh $file);
}

如果您想改用磁盘:

rename($qfn, "$qfn.old")
   or die "Can't rename \"$qfn\": $!\n";

open(my $fh_in, '<', "$qfn.old")
      or die "Can't open \"$qfn\": $!\n";
open(my $fh_out, '>', $qfn)
      or die "Can't create \"$qfn\": $!\n";

while (<$fh_in>) {
   chomp;
   $_ = "<$_>";
   print($fh_out "$_\n");
}

unlink("$qfn.old");

使用技巧,上面的内容可以简化为

local @ARGV = $qfn;
local $^I = '';
while (<>) {
   chomp;
   $_ = "<$_>";
   print(ARGV "$_\n");
}

或者作为一个单行:

perl -i -pe'$_ = "<$_>"' file

答案 1 :(得分:4)

读取内存中的内容,然后在写入文件时准备必需的字符串。 (需要SEEK_SET到零字节。

#!/usr/bin/perl

open(INFILE, "+<in.txt");
@a=<INFILE>;
seek INFILE, 0, SEEK_SET ;
foreach $i(@a)
{ 
    chomp $i;
    print INFILE "<".$i.">"."\n";
}

如果您担心在内存中读取的数据量,则必须创建临时结果文件,最后将结果文件复制到原始文件。

答案 2 :(得分:2)

您可以使用Tie::File轻松随意访问文件中的行:

use Tie::File;
use strict;
use warnings;

my $filename = "out.txt";
my @array;
tie @array, 'Tie::File', $filename or die "can't tie file \"$filename\": $!";

for my $line (@array) {
  $line = "<$line>";
  # or $line =~ s/^(.*)$/<$1>/g; # -- whatever modifications you need to do
}

untie @array;

免责声明:当然,此选项仅在文件未与其他进程共享时才可行。否则,您可以在修改文件时使用flock来阻止共享访问。

免责声明-2(感谢ikegami):如果您需要编辑大文件并关注性能,请不要使用此解决方案。对于小文件(小于2MB,尽管可以使用memory arg进行配置),大多数性能损失都得到了缓解。

答案 3 :(得分:1)

一个选项是打开文件两次:以只读方式打开它,读取数据,关闭数据,处理数据,再次打开读写(无追加),写入数据,然后关闭它。这是一种很好的做法,因为它可以最大限度地缩短文件打开的时间,以防其他人需要它。

如果您只想打开一次,那么您可以使用+<文件类型 - 只需在读取和写入之间使用seek调用即可返回文件的开头。否则,你完成阅读,在文件的末尾,并开始写在那里,这就是你得到你所看到的行为的原因。

答案 4 :(得分:0)

需要指定

use Fcntl qw(SEEK_SET);

为了使用

seek INFILE, 0, SEEK_SET;

感谢user1703205的例子。