当我尝试编辑文件时,为什么我的Perl脚本会删除整个文件的内容?

时间:2009-06-02 18:59:36

标签: file perl

我正在运行以下代码来打开文件(测试)并编辑(搜索和替换)它。程序似乎打开文件,但不是替换它删除文件中的所有内容。我不确定为什么会这样。有人可以帮我从这里出去吗?

#!use/bin/perl
use strict;
use warnings;

my $line = $ARGV[0];
my $find = '\s{6}seqfile\s=\sinfile';
my $replace = '\s{6}seqfile\s=\sinfil2';

open (FILE, ">/home/shubhi/Desktop/pamlrun/test") || die "cant open file \n";
my @body = <FILE>;
foreach $line(@body)
{
(s/$find/$replace/g);
{
print FILE "$line";
}
}
close(FILE);
print "reached here\n";
exit;

4 个答案:

答案 0 :(得分:7)

open(FILE, ">filename")以替换模式打开文件,写下以前的文件。

此外,您无法在替换模式$replace中使用正则表达式。

如果我理解你的意图,可以用单行

代替
perl -pi -e 's/(\s{6}seqfile\s=\sinfil)e/${1}2/' /home/shubhi/Desktop/pamlrun/test

答案 1 :(得分:5)

你的open()正在打开一个文件句柄来写入你的文件。取代

open (FILE, ">/home/shubhi/Desktop/pamlrun/test") || die "cant open file \n";

open (FILE, "/home/shubhi/Desktop/pamlrun/test") || die "cant open file \n";

在您发布的代码中,它会立即创建此文件以仅用于输出。您应该打开文件,读取/处理内容,然后将其写出来。如果文件大小合适,则在读取旧文件时写入 new 文件,并在(成功)完成后替换旧文件。

答案 2 :(得分:4)

看起来你想要就地编辑魔术。最简单的方法是使用$^I加上@ARGV加上<>的魔力(在I/O Operators section中查找空文件句柄):

#!/usr/bin/perl

use strict;
use warnings;

my $find = qr/\s{6}seqfile\s=\sinfile/;
my $replace = '      seqfile = infil2';

@ARGV = ("/home/shubhi/Desktop/pamlrun/test");

$^I = ".bak"; #safe the old files as file.bak

while (<>) {
    s/$find/$replace/g;
    print;
}

另外,考虑到正则表达式的性质,您可能希望[ ](匹配空格)或\t(匹配标签)而不是\s\s将匹配制表符,空格和其他空格字符。

您也可以使用Tie::File,但它似乎没有提供备份功能:

#!/usr/bin/perl

use strict;
use warnings;

use Tie::File;

my $find = qr/\s{6}seqfile\s=\sinfile/;
my $replace = '      seqfile = infil2';

tie my @lines, "Tie::File", "testdata"
    or die "could not open file: $!";

for my $line (@lines) {
    $line =~ s/$find/$replace/g;
}

当然,您可以使用File::Copy滚动自己的备份:

#!/usr/bin/perl

use strict;
use warnings;

use Tie::File;
use File::Copy;

my $find = qr/\s{6}seqfile\s=\sinfile/;
my $replace = '      seqfile = infil2';

copy "testdata", "testdata.bak"
    or die "could not backup file: $!";

tie my @lines, "Tie::File", "testdata"
    or die "could not open file: $!";

for my $line (@lines) {
    $line =~ s/$find/$replace/g;
}

如果我没有指出这基本上是一个单行的话,我也会疏忽:

perl -pi.bak -e 's/\s{6}seqfile\s=\sinfile/      seqfile = infil2/' testdata

利用\K(零宽度正向后视),Perl 5.10可以进一步缩短这一点:

perl -pi.bak -e 's/\s{6}seqfile\s=\s\Kinfile/infil2/' testdata

答案 3 :(得分:1)

open for write ='&gt;' 打开读取='&lt;'