我在剧本中看到了这个奇怪的问题。我有一个perl脚本,我试图删除包含模式的行。
system ("sed '/_pattern_>/d' _path_to_file_ -i");
但这会删除文件中的所有行。我很迷惑?我做错了吗?
在此处添加PERL代码:
#!/bin/env iperl
my $size = shift @ARGV || 500; # sample size
my @sample;
my $ldc_pa_tlist = "_path_to_list1_";
system ("p4 revert $ldc_pa_tlist");
sysem ("p4 sync $ldc_pa_tlist");
system ("p4 edit $ldc_pa_tlist");
open FH1, "<", "_Master_List_" or die "Couldn't open file : $! \n";
open FH2, ">", $ldc_pa_tlist or die "Couldn't open file : $! \n";
my $taken = 0; # for making sure we get the first $size lines
while( my $line = <FH1> ) {
chomp $line;
if ( rand(1) < ($size/$.) ){
my $position;
do{
$position = int rand($size);
}
while( $taken < $size && $sample[$position] );
$sample[$position] = $line;
$taken++;
}
}
system ("sed '/2frame/d' $ldc_pa_tlist -i");
while ( my $out_line = <FH2> ) {
next unless ($out_line =~ m/_some_pattern_/);
for( my $i = 0; $i < @sample; $i++ ){
print FH2 "$sample[$i] add_opt=\"-2frame\" add_opt=\"-mr_freq_shift:0\"\n";
}
last; #exit while loop
}
close FH1;
close FH2;
谢谢
答案 0 :(得分:1)
这里有一些问题:
首先,当你这样做时:
open FH2, ">", $ldc_pa_tlist or die "Couldn't open file : $! \n";
您正在打开输出文件并将文件截断为空(这是">"
对open
函数的作用。
在Perl中打开文件后,当您使用sed
标志运行-i
命令时,再次打开它:system ("sed '/2frame/d' $ldc_pa_tlist -i");
。您不希望从两个不同的程序同时打开同一个文件进行修改。
基本上,当您运行sed
命令sed
时,将以只读方式打开指定文件并打开一个新的临时文件读写。它正在读取原始文件,处理删除任何匹配的行,并将结果写入新的临时文件。 sed
然后关闭这两个文件并移动(重命名)新的临时文件以替换原始文件名。如果您在其他地方打开了原始文件(就像您一样),现在您将获得一个已从文件系统中删除的文件,并且在您关闭文件描述符时将不再存在。
当您已在另一个程序中打开该文件时,您正在使用与sed
输出不同的文件。
您最好的选择是使用Perl替换sed
功能。根据文件的大小,最简单的方法是将整个文件的内容读入内存,删除不需要的条目,然后将其写回。如果文件太大而无法以这种方式处理,您可以执行类似于sed
,打开文件进行读取和写入文件,并从输入中读取,过滤掉您不想要的行,并将它们写入输出。
另外,如上所述,您可能想要替换:
open FH2, ">", $ldc_pa_tlist or die "Couldn't open file : $! \n";
使用:
open FH2, "+<", $ldc_pa_tlist or die "Couldn't open file : $! \n";
这将打开文件进行读写,但打开时不会破坏它(删除内容)。