Как я могу сделать массовый поиск и заменить на Perl? - PullRequest
6 голосов
/ 28 мая 2009

У меня есть следующий скрипт, который принимает входной файл, выходной файл и заменяет строку во входном файле другой строкой и записывает выходной файл.

Я хочу изменить скрипт для прохождения через каталог файлов т.е. вместо запроса входных и выходных файлов, скрипт должен в качестве аргумента путь к каталогу, такой как C: \ temp \ allFilesTobeReplaced \ и найдите строку x и замените ее на y для всех файлов под этим путь к каталогу и выведите те же файлы.

Как мне это сделать?

Спасибо.

$file=$ARGV[0];

open(INFO,$file);
@lines=<INFO>;
print @lines;

open(INFO,">c:/filelist.txt");

foreach $file (@lines){
   #print "$file\n";
   print INFO "$file";
}

#print "Input file name: ";
#chomp($infilename = <STDIN>);

if ($ARGV[0]){
   $file= $ARGV[0]
}

print "Output file name: ";
chomp($outfilename = <STDIN>);
print "Search string: ";
chomp($search = <STDIN>);
print "Replacement string: ";
chomp($replace = <STDIN>);

open(INFO,$file);
@lines=<INFO>;
open(OUT,">$outfilename") || die "cannot create $outfilename: $!";

foreach $file (@lines){    
    # read a line from file IN into $_
    s/$search/$replace/g; # change the lines
    print OUT $_; # print that line to file OUT
}
close(IN);
close(OUT);

Ответы [ 5 ]

11 голосов
/ 28 мая 2009

Использование Perl Single Liner

perl -pi -e 's/original string/new string/' filename

можно объединить с File::Find, чтобы получить следующий отдельный скрипт (этот шаблон я использую для многих таких операций).

use File::Find;

# search for files down a directory hierarchy ('.' taken for this example)
find(\&wanted, ".");

sub wanted
{
    if (-f $_)
    {
        # for the files we are interested in call edit_file().
        edit_file($_);
    }
}

sub edit_file
{
    my ($filename) = @_;

    # you can re-create the one-liner above by localizing @ARGV as the list of
    # files the <> will process, and localizing $^I as the name of the backup file.
    local (@ARGV) = ($filename);
    local($^I) = '.bak';

    while (<>)
    {
        s/original string/new string/g;
    }
    continue
    {
        print;
    }
}
2 голосов
/ 28 мая 2009

Вы можете сделать это с параметром -i:

Просто обработайте все файлы как обычно, но включите -i.bak:

#!/usr/bin/perl -i.bak

while ( <> ) {
   s/before/after/;
   print;
}

Это должно обработать каждый файл и переименовать оригинал в original.bak. И, конечно, вы можете сделать это как одну строку, как упомянуто @Jamie Cook

1 голос
/ 28 мая 2009

Я знаю, что вы можете использовать простой однострочный Perl из командной строки, где имя файла может быть одним именем файла или списком имен файлов. Возможно, вы могли бы объединить это с ответом bgy, чтобы получить желаемый эффект:

perl -pi -e 's/original string/new string/' filename

И я знаю, что это банально, но это очень похоже на sed, если вы можете использовать инструменты gnu:

for i in `find ./allFilesTobeReplaced`; do sed -i s/original string/new string/g $i; done
1 голос
/ 28 мая 2009

Попробуйте это

#!/usr/bin/perl -w

@files = <*>;
foreach $file (@files) {
  print $file . '\n';
}

Взгляните также на glob в Perl:

0 голосов
/ 28 апреля 2014

имя файла perl -pi -e # OLD # NEW # g '. Вы можете заменить имя файла шаблоном, который подходит вашему списку файлов.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...