Perl:在数组中快速替换多个单词的出现次数

3
抱歉如果这是一个重复的主题,但我已经在论坛内搜索过,并且只找到了类似但不完全相同的问题。
我的问题是:
我有一个字符串数组,像这样:
@array = ("My name is "Annie" \n", "My mother's name was "Annie", too. \n", "I am "27" years old \n", "I live in "Minnesota" \n");

还有一个类似这样的字符串数组:

@subs = ("Annie", "22", "Minnesota");

我希望:
1)在第一个数组中查找第二个数组中的任何单词出现的情况(例如:Annie会与第一个和第二个元素匹配,Minnesota只与最后一个元素匹配)。
2)将所有与第二个数组中任何元素匹配的单词替换为相同的单词后跟“-DATA”(例如:“我的名字是“Annie-DATA”\n”)。
我想这可以很容易地通过一两个for循环来完成,但我想知道是否有更快的方法,也许可以巧妙地使用PERL的正则表达式。
谢谢!

1
真正的问题不应该只是添加-DATA,对吧?可能有更好的方法来看待这个问题。 - aartist
你的意思是什么?也许我应该说明一下,我的程序的真正输入/输出比我发布的这个例子要复杂得多。 然而,我也有一种感觉,可能是因为我的算法的这部分(此处未显示)感觉有点混乱,所以你说得对。 - selenocysteine
3个回答

2
您可以像这样进行替换:
s/(Annie|22|Minnesota)/\1-DATA/g

谢谢!只有一个问题:如果我事先不知道我必须匹配的3个关键词(在这种情况下是Annie,22,Minnesota),而是它们来自一个可以在长度和内容上都可能改变的数组,那该怎么办? - selenocysteine
2
$sub = join '|', @sub; s/($sub)/\1-DATA/g; $sub = join '|', @sub; s/($sub)/\1-DATA/g; - aartist

2

一个解决方案:

use strict;
use warnings;
my @array = ("My name is \"Annie\" \n",
   "My mother's name was \"Annie\", too. \n",
   "I am \"27\" years old \n",
   "I live in \"Minnesota\" \n");
my @subs = ("Annie", "22", "Minnesota");

my @new_array = map { my $line = $_; 
                      $line =~ s/$_/$_-DATA/g foreach @subs; 
                      $line } @array;

1

另一个解决方案也可以转义元字符:

# escape possible meta characters and join
my $sub = join '|', map { quotemeta } @subs;

# replace in the array
s/($sub)/$1-DATA/g for @array;

如果您不想直接更改@array中的值,请使用map而不是for。 例如:my @new = map s/($sub)/$1-DATA/g, @array;

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接