如何在大文件中删除包含subStr1和subStr2的行?

时间:2010-02-10 09:08:35

标签: perl file-io

如何删除大文件中包含subStr1subStr2的整行,并另存为新的小文件。

我的部分文件内容如下。

12-23 20:27:35:265   GetVariable [Tunnel]    INFO  iVid = 536876042 data [Reruen] = System.Object[]
12-23 20:27:35:265   GetVariable [Tunnel]    INFO  iVid = 536876043 data [Reruen] = System.Object[]
12-23 20:27:33:718   SendEvent [Link]    INFO  eventID = 268435564
12-23 20:27:33:718   WaferMove [Link]    INFO  waferNumber = 122253 UNIT_ID dest = UNIT_ID_LL_A  slot = 1 bool isStarted = False
12-23 20:27:35:265   GetVariable [Tunnel]    INFO  iVid = 536876042 data [Reruen] = System.Object[]
12-23 20:27:35:265   GetVariable [Tunnel]    INFO  iVid = 536876043 data [Reruen] = System.Object[]
12-23 20:27:33:765   WaferMove(d) [Link]    INFO  waferNumber = 122253 UNIT_ID dest = UNIT_ID_LL_A  slot = 1 bool isStarted = False

我想要删除包括GetVariable [Tunnel]System.Object[]在内的所有行 像下面的行。感谢。

12-23 20:27:35:265   GetVariable [Tunnel]    INFO  iVid = 536876043 data [Reruen] = System.Object[]

6 个答案:

答案 0 :(得分:3)

使用Perl's -i switch进行就地编辑:

$ perl -i.bak -ne 'print unless /GetVariable\s+\[Tunnel]/ &&
                                /System.Object\[]/' file.log

这将在file.log.bak中保留原始文件的备份,过滤后的版本将位于file.log

答案 1 :(得分:2)

如果您能负担得到该文件的副本(这可能更安全),那么您可以打开两个文件(一个用于读取原始文件一个用于写入结果文件)并跳过您找到的文件行匹配:

open(ORIG, '<', 'orig.txt');
open(RESULT, '>', 'result.txt');
while(my $line = <ORIG>) {
  # fine tune this
  next if $line =~ /GetVariable\s+\[Tunnel\].*System\.Object\[\]/;
  print RESULT $line;
}
close ORIG;
close RESULT;

我没有尝试过该脚本,因此请务必先在示例文件中对其进行测试。

编辑:您需要调整正则表达式。玩一点。

答案 2 :(得分:2)

perl -ne 'm/\QGetVariable [Tunnel]\E.*?\QSystem.Object[]\E/ || print;' data.log > data.log.new

然后只需将data.log.new重命名为data.log

答案 3 :(得分:2)

很抱歉这是一个非Perl的答案,但我会自发地使用grep:

grep -v "GetVariable \[Tunnel\].*System\.Object\[\]" infile > outfile

这可以使用Perl来完成:

perl -wne'print unless m/GetVariable \[Tunnel\].*System\.Object\[\]/' < infile > outfile

答案 4 :(得分:1)

while (<>) {
    chomp;
    next if (/GetVariable \[Tunnel\]/ && /System.Object\[\]/);
    print $_ ."\n";

}

在命令行上

$ perl myscript.pl inputfile > newfile

以上工作也适用于“GetVariable [Tunnel]”之前的“System.Object []”,它不会删除行上只有其中一种模式的行。

perl -ne 'print if($_!~/GetVariable \[Tunnel\]/ && $_ !~ /System.Object\[\]/)' file

答案 5 :(得分:1)

请参阅perlfaq5How do I change, delete, or insert a line in a file, or append to the beginning of a file?的回答:

<小时/> 如何更改,删除或插入文件中的行,或附加到文件的开头?

(由brian d foy提供)

从文本文件中插入,更改或删除行的基本思想包括读取和打印文件到要进行更改的位置,进行更改,然后读取和打印文件的其余部分。 Perl不提供对行的随机访问(特别是因为记录输入分隔符$ /,是可变的),尽管像Tie :: File这样的模块可以伪造它。

执行这些任务的Perl程序采用打开文件,打印行,然后关闭文件的基本形式:

open my $in,  '<',  $file      or die "Can't read old file: $!";
open my $out, '>', "$file.new" or die "Can't write new file: $!";

while( <$in> )
    {
    print $out $_;
    }

关闭$ out; 在该基本表单中,添加您需要插入,更改或删除行的部分。

要将行添加到开头,请在进入打印现有行的循环之前打印这些行。

open my $in,  '<',  $file      or die "Can't read old file: $!";
open my $out, '>', "$file.new" or die "Can't write new file: $!";

print $out "# Add this line to the top\n"; # <--- HERE'S THE MAGIC

while( <$in> )
    {
    print $out $_;
    }

关闭$ out; 要更改现有行,请插入代码以修改while循环内的行。在这种情况下,代码找到所有小写版本的“perl”并将它们大写。每一行都会发生这种情况,所以请确保你应该在每一行都这样做!

open my $in,  '<',  $file      or die "Can't read old file: $!";
open my $out, '>', "$file.new" or die "Can't write new file: $!";

print $out "# Add this line to the top\n";

while( <$in> )
    {
    s/\b(perl)\b/Perl/g;
    print $out $_;
    }

关闭$ out; 要仅更改特定行,输入行号$。是有用的。首先阅读并打印到您想要更改的行。接下来,阅读您要更改的单行,更改并打印它。之后,阅读其余部分并打印出来:

while( <$in> )   # print the lines before the change
    {
    print $out $_;
    last if $. == 4; # line number before change
    }

my $line = <$in>;
$line =~ s/\b(perl)\b/Perl/g;
print $out $line;

while( <$in> )   # print the rest of the lines
    {
    print $out $_;
    }

要跳过行,请使用循环控件。此示例中的下一个跳过注释行,最后一个在遇到 END DATA 时停止所有处理。

while( <$in> )
    {
    next if /^\s+#/;             # skip comment lines
    last if /^__(END|DATA)__$/;  # stop at end of code marker
    print $out $_;
    }

通过使用next来跳过您不想在输出中显示的行来删除特定行。此示例每隔五行跳过一次:

while( <$in> )
    {
    next unless $. % 5;
    print $out $_;
    }

如果由于一些奇怪的原因,你真的想要一次看到整个文件而不是逐行处理,你可以把它捏进去(只要你能把整个文件放在内存中!):< / p>

open my $in,  '<',  $file      or die "Can't read old file: $!"
open my $out, '>', "$file.new" or die "Can't write new file: $!";

my @lines = do { local $/; <$in> }; # slurp!

    # do your magic here

print $out @lines;

File :: Slurp和Tie :: File等模块也可以提供帮助。但是,如果可以,请避免立即读取整个文件。在进程完成之前,Perl不会将该内存返回给操作系统。

您还可以使用Perl单行来就地修改文件。以下内容将inFile.txt中的所有'Fred'更改为'Barney',并使用新内容覆盖文件。使用-p开关,Perl在您使用-e指定的代码周围环绕一个while循环,-i打开就地编辑。当前行在$ 中。使用-p,Perl会在循环结束时自动打印$ 的值。有关详细信息,请参阅perlrun。

perl -pi -e 's/Fred/Barney/' inFile.txt

要备份inFile.txt,请为-i添加一个文件扩展名:

perl -pi.bak -e 's/Fred/Barney/' inFile.txt

要仅更改第五行,您可以添加测试检查$。,输入行号,然后仅在测试通过时执行操作:

perl -pi -e 's/Fred/Barney/ if $. == 5' inFile.txt

要在某一行之前添加行,您可以在Perl打印$ _之前添加一行(或多行!):

perl -pi -e 'print "Put before third line\n" if $. == 3' inFile.txt

您甚至可以在文件的开头添加一行,因为当前行在循环结束时打印:

perl -pi -e 'print "Put before first line\n" if $. == 1' inFile.txt

要在文件中已经有一行之后插入一行,请使用-n开关。它就像-p,除了它在循环结束时不打印$ _,所以你必须自己做。在这种情况下,首先打印$ _,然后打印要添加的行。

perl -ni -e 'print; print "Put after fifth line\n" if $. == 5' inFile.txt

要删除行,只打印您想要的行。

perl -ni -e 'print unless /d/' inFile.txt

    ... or ...

perl -pi -e 'next unless /d/' inFile.txt