使用Perl从文件中删除元素

时间:2011-08-12 09:52:01

标签: perl

INPUT.TXT

CASE
    REPEAT 1 TIMES
    ENDREPEAT
ENDCASE
    REPEAT
    ENDREPEAT
CASE
    REPEAT 2 TIMES
    ENDREPEAT
ENDCASE

code.pl

open (FH, "input.txt");
my @arr = <FH>;

foreach (@arr) {
    if ($_ =~ s/ENDCASE.*?CASE//gsi) {
       $_ = s/ENDCASE.*?CASE//gsi;
    }
}
print @arr;

输出:perl code.pl

它打印数组而不修改........

CASE
    REPEAT 1 TIMES
    ENDREPEAT
ENDCASE
    REPEAT        ===> To be Removed
    ENDREPEAT     ===> To be Removed
CASE
    REPEAT 2 TIMES
    ENDREPEAT
ENDCASE

需要的输出是, * ** |||||||||||| < /强> ** * *

CASE
    REPEAT 1 TIMES
    ENDREPEAT
ENDCASE
************Content Removed*****************
CASE
    REPEAT 2 TIMES
    ENDREPEAT
ENDCASE

请指导我获取此输出。

提前致谢.........

4 个答案:

答案 0 :(得分:4)

这可以通过命令行以及la flip-flop operator来完成。


只需将结果输出到屏幕

$ perl -ne 'print if /^CASE/ .. /^ENDCASE/' Input.txt

将输出定向到另一个文件

$ perl -ne 'print if /^CASE/ .. /^ENDCASE/' Input.txt > output.txt

要就地修改文件

$ perl -ni.bak -e 'print if /^CASE/ .. /^ENDCASE/' Input.txt

如果在Windows上,请将'(单引号)替换为"(双引号)。

答案 1 :(得分:1)

您有几种方法可以解决您的问题,但您可能有兴趣了解为什么您的解决方案不起作用。有几个原因。

首先,当你将文件读入@arr时,你会在数组的每个元素中得到一行文件。当你在数组处理一个元素时,没有任何元素同时包含ENDCASE和CASE,所以你的正则表达式永远不会匹配,也没有任何改变。

对于您的工作方法,您需要重写程序以一次处理整个文件。 (我还清理了一些代码。)

#!/usr/bin/perl

use strict;
use warnings;

open (my $fh, '<', 'input.txt') or die $!;
my $file = do { local $/; <$fh> };

$file =~ s/ENDCASE.*?CASE//gsi;

print $file;

但这并不能解决问题。它给出了输出:

CASE
    REPEAT 1 TIMES
    ENDREPEAT

    REPEAT 2 TIMES
    ENDREPEAT
ENDCASE

那是因为ENDCASE和CASE包含在你的正则表达式中,所以它们被删除了。您需要在perlre中查看前瞻和后瞻断言来解决此问题。我将把它作为读者的练习。

答案 2 :(得分:0)

使用Tie::File绑定文件:

tie @array, 'Tie::File', filename or die ...;

以您认为合适的任何方式操纵线条,然后解开阵列:

untie @array;   

因此,您的修改将反映在原始文件中。

答案 3 :(得分:0)

这是一个奇怪的想法,可能会奏效。

use English qw<$INPLACE_EDIT $RS>;
$INPLACE_EDIT = '.bak';
local $RS     = "CASE\n";

while ( <$input> ) {
    print(( !/^(END)?CASE\n\z/ms or $1 ) ? $_ : $RS );
}

这个想法是你不是通过换行符而是通过CASE + \n来分解你的记录,因此你可以将ENDCASE和CASE之间的所有行视为一条你可以简单地用{替换的记录{1}}。

请注意,我们只是打印记录,除非我们在'ENDCASE'或'CASE'之前看到一行开头,然后是换行符。因此,即使在分解记录时我们做了一个非常脆弱的假设,我们在修改记录之前检查我们的假设。如果它与"CASE\n"匹配,则"ENDCASE\n"$1,我们会不加修改地打印该记录。

这个可以打破。如果由于某种原因你有能力在这里发表评论:

'END'

然后将打印第一行。所以我们可以这样做:

ENDCASE
    REPEAT       ===> This prints because it ends with CASE
    ENDREPEAT     
CASE