2011-08-12 7 views
1

INPUT.TXTは、Perl

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 

この出力を得るために私をガイドしてください。事前に

おかげで.........

+0

少なくとも、データ/コードとは何かを明確にするように質問してください。 –

+0

「CASE/ENDCASEの間に削除されたもの」または「REPEAT/ENDREPEATがCASE/ENDCASEに組み込まれていない限り削除される」かどうかを指定する必要があります。この例では、出力は同じです。より一般的なケースでは、そうではありません。また、 'REPEAT n TIMES/REPEAT m TIMES/ENDREPEAT/ENDREPEAT'で何が起こるべきかを指定する必要があります。そして、その言語がこれらのキーワードを最初の非空文字列として必要とすると仮定するのは安全でしょうか?あるいはレイアウトフリーフォームですか? –

答えて

0

Tie::Fileを使用してファイルを結ぶ:

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

は、あなたが合うどのような方法で、ラインを操作して、配列をほどきます:

untie @array; 

このように、変更内容は元のファイルに反映されます。

4

これは、コマンドラインからもflip-flop operatorで実行できます。


だけ出力結果がその場で

をファイルを変更するには、別のファイル

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

への出力を指示する

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

をスクリーニングするために、

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

Windows上の場合"(二重引用符)で'(一重引用符)を交換してください。

1

あなたの問題に対処する方法のいくつかの提案がありますが、あなたの解決策が機能しなかった理由を聞くことに興味があるかもしれません。いくつかの理由があります。

まず、ファイルを@arrに読み込むと、配列の各要素に1行のファイルが得られます。そして、配列のある時点で要素を処理するとき、要素に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は正規表現に含まれているため、削除されます。この問題を解決するには、先読みとlookbehindアサーションをperlreに表示する必要があります。私はそれを読者のための練習として残しておきます。

+0

これはinput.txtの大きさによって異なります。相対的に大きければ、ファイル全体をメモリにロードする理由はまったくありません。 –

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とによって、あなたは単に"CASE\n"に置き換えることができます一つのレコードとしてENDCASEとCASEの間のすべての行を処理するために取得。私たちは改行が続く「ENDCASE」または「CASE」の前の行の開始を参照してくださいしない限り、我々は、単にレコードを印刷する

注意。したがって、レコードを分割するときにかなり脆弱な仮定をしても、レコードを変更する前に仮定をチェックします。それは"ENDCASE\n"と一致した場合にも、その後$1'END'であり、我々はそのまま、そのレコードを印刷します。

このしかし、破ることができます。何らかの理由でここにコメントがある場合:

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

最初の行が印刷されます。だから私たちはこれを行うことができます:

my $match = 0; 
my $old_1; 
while (<$input>) { 
    if (m/^(END)?CASE\n\z/ms and not $1) { 
     print $RS; 
    } 
    else { 
     next if $old_1; 
     print; 
    } 
    $old_1 = $1; 
}  
+0

ここで私は 'split /'を '$ /'使い方にするのが好きだと思います。例えば、 'split /(?= \ nCASE \ n)/、$ _;'コメントも簡単に補うことができます。 – TLP