2013-04-04 5 views
2

Извините, если это повторяющаяся тема, но я искал внутри форума, и я нашел только похожие, но не одинаковые вопросы.Perl: быстрая замена появления нескольких слов в массиве

Моя проблема:

У меня есть массив строк, как это:

@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"); 

Я хотел бы to:

1) найти любое вхождение слов из второго массива в первом массиве (например: Энни соответствовала бы первому и второму элементу, штат Миннесота, только с последним).

2) замените все слова, которые соответствуют любому элементу второго массива с тем же словом, за которым следует «-DATA» (например: «Меня зовут« Annie-DATA »\ n»).

Я думаю, что это можно было бы легко сделать с помощью одного или двух циклов, но мне интересно, есть ли какой-нибудь более быстрый способ, возможно, с помощью умного использования регулярных выражений PERL.

Спасибо!

+1

Настоящая проблема не должна быть добавлена ​​-DATA или не так ли? Там может быть лучший способ взглянуть на проблему. – aartist

+0

Что это значит? Возможно, мне следует указать, что реальный ввод/вывод моей программы намного сложнее, чем в этом примере, который я опубликовал. Однако у меня также есть ощущение, что я могу столкнуться с проблемой неправильно, потому что эта часть моего алгоритма (не показана здесь) немного запутана, поэтому вы можете быть правы. – selenocysteine

ответ

2

Вы могли бы заменить так:

s/(Annie|22|Minnesota)/\1-DATA/g 
+0

Спасибо! Только вопрос: но что, если я заранее не знаю 3 ключевых слова, которые мне нужно сопоставить (в данном случае, Annie, 22, Minnesota), но они исходят из массива, который может меняться как по длине, так и по содержанию? – selenocysteine

+2

$ sub = join '|', @sub; с/($ суб)/\ 1-DATA/г; – aartist

+6

Используйте '$ 1', а не' \ 1'. – TLP

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;

Смежные вопросы