Perl регулярное выражение в регулярном выражении
В Perl много раз, когда я хочу заменить совпадающую строку на себя после того, как другой оператор замены будет выполнен в совпадении. Например, у меня есть приложение, в котором мне нужно найти строки в кавычках и удалить из них пробелы. Один из способов сделать это будет:
while($str =~ s/"([^"])+"//){
$temp = $1;
$temp2 = $temp;
$temp =~ s/ /_/g;
$str =~ s/$temp2/$temp1/;
}
Это также кажется возможным:
$str =~ s/"([^"])+"/replace_spaces($1)/gx;
sub replace_spaces(){
$word = shift;
$word =~ s/ /_/g;
return $word;
}
Есть ли чистый способ регулярного выражения сделать это, как-то вложив регулярное выражение в регулярное выражение?
3 ответа
Для конкретной задачи вам будет лучше использовать Text:: ParseWords:
#!/usr/bin/env perl
use strict; use warnings;
use feature 'say';
use Text::ParseWords;
my $input = q{This is "a t e s t " string. "Hello - world !"};
my @words = shellwords $input;
for my $word ( @words ) {
$word =~ s/ +//g;
say "'$word'";
}
См. Также Как я могу разделить строку, ограниченную [символами], кроме случаев, когда внутри [символ]?
Да, вы можете сделать это, но в каждой ситуации вам нужно изобретать новое регулярное выражение. В этом случае серебряной пули нет.
Вы должны изменить пробелы с подчеркиванием, но не все, только те, которые находятся внутри подстрок с разделителями кавычками. Последнее условие, которое вы проверяете, смотрит вперед и смотрит за утверждениями, но эти проверки не так легко сформулировать.
Например:
$ perl -pe 's/(?<=")(\S+)\s+(?=.*")/$1_/g;'
a b "c d" e f
a b "c_d" e f
Но это далеко не идеально. Это работает в самых простых ситуациях. Это не решение, это просто демонстрация идеи.
Вы можете попробовать:
$str =~ s{"([^"]+)"}{do{(local$_=$1)=~y/ /_/;$_}}eg;
Или для лучшей читаемости:
$str =~ s/
"([^"]+)" # all inside double quotes to $1
/ do{ # start a do block
local $_ = $1; # get a copy from $1
y| |_|; # transliterate ' ' to '_'
$_ # return string from block
} # end the do block
/xeg;
С уважением
БВ