如何进行批量搜索并用Perl替换?

时间:2021-07-25 16:52:14

I have the following script that takes in an input file, output file and replaces the string in the input file with some other string and writes out the output file.

我有以下脚本,它接收输入文件,输出文件并用其他字符串替换输入文件中的字符串并写出输出文件。

I want to change the script to traverse through a directory of files i.e. instead of prompting for input and output files, the script should take as argument a directory path such as C:\temp\allFilesTobeReplaced\ and search for a string x and replace it with y for all files under that directory path and write out the same files.

我想更改脚本遍历文件目录,即不是提示输入和输出文件,脚本应该将目录路径作为参数,例如C:\ temp \ allFilesTobeReplaced \并搜索字符串x并替换它使用y表示该目录路径下的所有文件并写出相同的文件。

How do I do this?

我该怎么做呢?

Thanks.

$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 个解决方案

#1


The use of the perl single liner

使用perl单衬垫

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

can be combined with File::Find, to give the following single script (this is a template I use for many such operations).

可以与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


You can do this with the -i param:

您可以使用-i param执行此操作:

Just process all the files as normal, but include -i.bak:

只需正常处理所有文件,但包含-i.bak:

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

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

This should process each file, and rename the original to original.bak And of course you can do it as a one-liner as mentioned by @Jamie Cook

这应该处理每个文件,并将原始文件重命名为original.bak当然,你可以像@Jamie Cook所提到的那样做一个单行程序。

#3


Try this

#!/usr/bin/perl -w

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

Take also a look to glob in Perl:

另请参阅Perl中的glob:

#4


I know you can use a simple Perl one-liner from the command line, where filename can be a single filename or a list of filenames. You could probably combine this with bgy's answer to get the desired effect:

我知道你可以在命令行中使用一个简单的Perl单行程序,其中filename可以是单个文件名,也可以是文件名列表。您可以将此与bgy的答案结合起来以获得所需的效果:

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

And I know it's trite but this sounds a lot like sed, if you can use gnu tools:

而且我知道它很陈腐,但这听起来很像sed,如果你可以使用gnu工具:

for i in `find ./allFilesTobeReplaced`; do sed -i s/original string/new string/g $i; done

#5


perl -pi -e 's#OLD#NEW#g' filename. You can replace filename with the pattern that suits your file list.

perl -pi -e's#OLD#NEW#g'filename。您可以使用适合您的文件列表的模式替换filename。

#1


The use of the perl single liner

使用perl单衬垫

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

can be combined with File::Find, to give the following single script (this is a template I use for many such operations).

可以与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


You can do this with the -i param:

您可以使用-i param执行此操作:

Just process all the files as normal, but include -i.bak:

只需正常处理所有文件,但包含-i.bak:

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

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

This should process each file, and rename the original to original.bak And of course you can do it as a one-liner as mentioned by @Jamie Cook

这应该处理每个文件,并将原始文件重命名为original.bak当然,你可以像@Jamie Cook所提到的那样做一个单行程序。

#3


Try this

#!/usr/bin/perl -w

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

Take also a look to glob in Perl:

另请参阅Perl中的glob:

#4


I know you can use a simple Perl one-liner from the command line, where filename can be a single filename or a list of filenames. You could probably combine this with bgy's answer to get the desired effect:

我知道你可以在命令行中使用一个简单的Perl单行程序,其中filename可以是单个文件名,也可以是文件名列表。您可以将此与bgy的答案结合起来以获得所需的效果:

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

And I know it's trite but this sounds a lot like sed, if you can use gnu tools:

而且我知道它很陈腐,但这听起来很像sed,如果你可以使用gnu工具:

for i in `find ./allFilesTobeReplaced`; do sed -i s/original string/new string/g $i; done

#5


perl -pi -e 's#OLD#NEW#g' filename. You can replace filename with the pattern that suits your file list.

perl -pi -e's#OLD#NEW#g'filename。您可以使用适合您的文件列表的模式替换filename。