ファイル~/foo
とは異なるファイルがあります~/remove.txt
。私は各行を繰り返しながら~/remove.txt
(行がある場所)文字列の各インスタンスを削除するPerlスクリプトを作成したいと思います。私のコードは(<LINE>)
~/foo
<LINE>
~/remove.txt
#! /usr/bin/perl
use strict;
use warnings;
sub main
{
my $infile = "remove.txt";
open(INPUT, $infile) or die "cannot open $infile";
while(my $line = <INPUT>)
{
chomp($line);
my $bad_string = "($line)";
system( q( perl -p -i -e 's/$bad_string//g' foo ) );
}
close(INPUT);
}
main();
しかし、このスクリプトを実行しても私のファイルはまったく変更されないようです。私のスクリプトに何の問題がありますか?
ベストアンサー1
あなたが要求した問題に加えて、あなたのスクリプトには、「remove.txt」のすべての行に対して「foo」をそのまま渡すという大きな欠陥があります。これは非常に非効率的です。より良いアプローチは、「remove.txt」を読み、長い正規表現を設定し、それを一度使用して「foo」を編集することです。
最も簡単な方法は、検索文字列を配列にプッシュしてから "|" "join()" 配列 (regex "or") 文字を使用して正規表現で使用できる文字列を作成します。
以下は、これを実行して元の問題を解決するスクリプトです。
#! /usr/bin/perl
use strict;
use warnings;
# first construct a regular expression containing every
# line that needs to be removed. This is so we only have
# to run a single pass through $infile rather than one
# pass per line in $removefile.
my @remove = ();
my $removefile='remove.txt';
open(REMFILE,"<",$removefile) || die "couldn't open $removefile: $!\n";
while(<REMFILE>) {
chomp;
next if (/^\s*$/);
push @remove, $_;
};
close(REMFILE);
# choose one of the following two lines depending on
# whether you want to remove only entire lines or text
# within a line:
my $remove = '^(' . join("|",@remove) . ')$';
#my $remove = join("|",@remove);
# now remove the unwanted text from all lines in $infile
my $infile = 'foo';
system('perl','-p','-i','-e',"s/$remove//g",$infile);
# if you want to delete matching lines, try this instead:
#system('perl','-n','-i','-e',"print unless /$remove/",$infile);