删除行的模式会导致在Sed中删除文件的全部内容

时间:2015-12-15 21:16:15

标签: regex bash perl sed

我在剧本中看到了这个奇怪的问题。我有一个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;

谢谢

1 个答案:

答案 0 :(得分:1)

这里有一些问题:

  • 您正在截断文件并期望它有数据
  • 你试图打开一个文件两次(一次在Perl内,一次在外面)
  • 您正在尝试从已写入的文件中读取
  • 你有竞争条件

首先,当你这样做时:

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";

这将打开文件进行读写,但打开时不会破坏它(删除内容)。