用perl替换字符串中的多个实例

时间:2009-06-25 06:57:30

标签: regex perl

我有以下用例,输入文件中的输入为:

Line1 : AA BB CC DD EE

我想用

替换它
1 2 3 4 5

输出

Line1: 1 2 3 4 5

在Perl的一个正则表达式中,我可以这样做吗

我正在尝试这个但是不成功

my @arr1 = ("AA", "BB", "CC", "DD", "EE");
open F2, $file;
my $count = 0;
while (<F2>) {
    my $str = $_;
    $str =~ s/$arr[$count]/$count+1/g;
    print to file
}

close(F2);

这不是任何想法的伎俩

5 个答案:

答案 0 :(得分:2)

如果我理解正确,你想用数字替换每个单词(每个单词后加1)。这是带有测试的程序:

#!/usr/bin/perl

use strict;
use warnings;
use Test::More qw(no_plan);

sub replace {
  my $str=shift;
  my $count=1;
  $str=~s/\w+/$count++/ge;
  return $str;
}


is(replace('AA AA DD EE'),'1 2 3 4');
is(replace('A B C D E'),'1 2 3 4 5');

答案 1 :(得分:2)

您需要做一些事情来修改您当前没有执行的文件。最简单的选择是使用File::Inplace(或输出到第二个文件)。

此外,您不是在数组上循环,而是在文件的行上循环,因此它将在每行上仅替换$ arr [0]为1。

  use strict;
  use warnings;
  use File::Inplace;

  my @replacees = ("AA", "BB", "CC", "DD", "EE");
  my $editor = new File::Inplace(file => "file.txt", regex => "\n");
  while (my ($line) = $editor->next_line) {
    my $count = 1
    for my $replacee (@replacees) { 
        if ($line =~ m/$replacee/) {
            $line =~ s/$replacee/$count/g;
        }
        $count = $count + 1;
    }
    $editor->replace_line($line);
  }
  $editor->commit;

答案 2 :(得分:2)

至于写入同一档案,请注意Vinko的回答。至于替换字符串,请查看以下代码段:

my @arr1 = ("AA", "BB", "CC", "DD", "EE");
my %replacements = map { ($arr1[$_] => $_ + 1) } (0..$#arr1);
my $regexp = join( '|', sort { length($b) <=> length($a) } @arr1);

open F2, $file;
while (<F2>) {
    my $str = $_;
    $str =~ s/($regexp)/$replacements{$1}/ge;
    print $str;
}
close(F2);

重要部分:

my %replacements = map { ($arr1[$_] => $_ + 1) } (0..$#arr1);

使用@ arr1中的键构建哈希值,值是@ arr1中给定值的索引,加1。

例如,对于@ arr1 =(“a”,“b”,“d”,“c”); %替换将是:(“a”=&gt; 1,“b”,=&gt; 2,“c”=&gt; 4,“d”=&gt; 3);

my $regexp = join( '|', sort { length($b) <=> length($a) } @arr1);

这构建了基本正则表达式,用于查找@ arr1中的所有单词。排序部分按其长度递减来排序单词。所以,对于@ arr1 =(“a”,“ba”,“bac”),$ regexp将是'bac | ba | a'。

这种排序很重要,否则如果任何单词都是任何其他单词的前缀(如我的例子中的“ba”和“bac”),就会出现问题。

总而言之,不鼓励使用文件句柄作为FH,因为它们是全局变量,并且在更复杂的程序中产生“有趣”的问题。而是像这样使用open:

open my $fh, 'filename';

或更好:

open my $fh, '<', 'filename';

答案 3 :(得分:0)

首先,纠正:

while (<F2>) {
    my $str = $_;

如果您希望读取的行在$str中结束,则没有理由让$_参与此过程:

while(my $ str =){

这也提出了depesz使用词汇文件句柄而不是打包全局裸字文件句柄的观点。

现在,看看你的循环:

my $count = 0;
while (my $str = <$input_fh>) {
    $str =~ s/$arr[$count]/$count+1/g;
    # ...
}

似乎有一个隐含的假设,即文件中的行数不能超过@foo中的元素数。在这种情况下,您无需使用$count$.也可以。假设你在第二行。您的代码表示您希望用BB替换该行上2的所有匹配项,这与您口头描述的内容不同。

这一点非常重要:您发布的任何代码都应与口头描述保持一致

无论如何,这是一种方式:

<强> rty.pl

#!/usr/bin/perl

use strict;
use warnings;

use File::Slurp;

my ($input) = @ARGV;

write_file(
    $input, [
        map { s/( ([A-Z]) \2 )/ord($2) - ord('A') + 1/gex; $_ } read_file $input
    ]
);
__END__

<强> test.data:

Line1 : AA BB CC DD EE
Line1 : AA BB CC DD EE
Line1 : AA BB CC DD EE
Line1 : AA BB CC DD EE

$ rty.pl test.data
脚本调用后

test.data:

Line1 : 1 2 3 4 5
Line1 : 1 2 3 4 5
Line1 : 1 2 3 4 5
Line1 : 1 2 3 4 5

答案 4 :(得分:0)

无论哪种方式都可行

my%arr2 =('AA'=&gt; 1,'BB'=&gt; 2,'CC'=&gt; 3,'DD'=&gt; 4,'EE'=&gt; 5,'FF “=→6);

打开F2,“t1.txt”;
打开F3,“&gt; out.txt”;
而(){
      我的$ str = $ ;
       print F3 join'',map {s / $
/ $ arr2 {$ } / g; $ } split / /,$ str;
       打印F3“\ n”;
}

接近(F2);
关闭(F3);

我的@ arr1 =(“AA”,“BB”,“CC”,“DD”,“EE”,“FF”);
我的%hashArr = map {($ arr1 [$ ] =&gt; $ + 1)}(0 .. $#arr1);

打开F2,“t1.txt”;
打开F3,“&gt; out.txt”;
而(){
     我的$ str = $ ;
     print F3 join'',map {s / $
/ $ hashArr {$ } / g; $ } split / /,$ str;
      打印F3“\ n”;
}

接近(F2);
关闭(F3);