Regex 在单个快照中查找并替换两个变量中的相同字符

Regex 在单个快照中查找并替换两个变量中的相同字符,regex,perl,Regex,Perl,我想在多个标量变量中查找和替换存储内容的标量变量(每个字符串的内容会有所不同),因此我需要为两个变量的相同替换插入两行 $str1=~s/\_/&underscore\;/g; $str1=~s/\^/&carrot\;/g; $str2=~s/\_/&underscore\;/g; $str2=~s/\^/&carrot\;/g; 是否有可能一次性/同时更换所有管柱。请注意,内容在字符串中会有所不同。(我问问题的方式可能是kid,但我正在替换200多行代码,

我想在多个标量变量中查找和替换存储内容的标量变量(每个字符串的内容会有所不同),因此我需要为两个变量的相同替换插入两行

$str1=~s/\_/&underscore\;/g;
$str1=~s/\^/&carrot\;/g;

$str2=~s/\_/&underscore\;/g;
$str2=~s/\^/&carrot\;/g;

是否有可能一次性/同时更换所有管柱。请注意,内容在字符串中会有所不同。(我问问题的方式可能是kid,但我正在替换200多行代码,但试图减少编码行)

您可以将变量放入
for
循环中,该循环将依次为每个变量别名
$。注意,在正则表达式模式中,下划线和分号都不需要转义

for ( $str1, $str2 ) {
    s/_/&underscore;/g;
    s/\^/&carrot;/g;
}

然而,这两者都是非标准实体。你自己申报了吗?你可能指的是插入符号,而不是胡萝卜,胡萝卜是一种蔬菜!我见过它叫
&Hat,但我认为这也是非标准的。您可以始终使用
^
(下划线为
_;

您可以将变量放入
for
循环中,该循环将依次为每个变量别名
$
。注意,在正则表达式模式中,下划线和分号都不需要转义

for ( $str1, $str2 ) {
    s/_/&underscore;/g;
    s/\^/&carrot;/g;
}

然而,这两者都是非标准实体。你自己申报了吗?你可能指的是插入符号,而不是胡萝卜,胡萝卜是一种蔬菜!我见过它叫
&Hat,但我认为这也是非标准的。您可以始终使用
^
(下划线为
_;

最简单的方法可能是定义映射规则,根据这些规则构建正则表达式,并提供应用它们的函数。这里有一个尝试:

my %map = (
  "_" => "&underscore;",
  "^" => "⁁",
);

sub apply_map {
  $_[0] =~ s/(${\
    join "|", map quotemeta, keys %map
  })/$map{$1}/g;
}

apply_map $str1;
apply_map $str2;
并且,借用Borodin的答案,将映射应用于更少语句中的多个字符串:

foreach ($str1, $str1) {
  apply_map $_;
}
或者,修改apply_map以接受多个参数:

sub apply_map {
  s/(${\
    join "|", map quotemeta, keys %map
  })/$map{$1}/g foreach @_;
}

apply_map $str1, $str2;

请注意
quotemeta
。这可以防止映射键中的任何特殊字符影响regexp的行为。我还使用
${\..}
语法在
s//
中插入表达式,但构建单独的模式字符串可能更清晰。如果要替换的所有内容都是一个字符长,那么可以使用
'
连接,并使用字符类(例如
[\u^]
),而不是使用

连接,最简单的方法可能是定义映射规则,根据这些规则构建正则表达式,并提供应用这些规则的函数。这里有一个尝试:

my %map = (
  "_" => "&underscore;",
  "^" => "⁁",
);

sub apply_map {
  $_[0] =~ s/(${\
    join "|", map quotemeta, keys %map
  })/$map{$1}/g;
}

apply_map $str1;
apply_map $str2;
并且,借用Borodin的答案,将映射应用于更少语句中的多个字符串:

foreach ($str1, $str1) {
  apply_map $_;
}
或者,修改apply_map以接受多个参数:

sub apply_map {
  s/(${\
    join "|", map quotemeta, keys %map
  })/$map{$1}/g foreach @_;
}

apply_map $str1, $str2;

请注意
quotemeta
。这可以防止映射键中的任何特殊字符影响regexp的行为。我还使用
${\..}
语法在
s//
中插入表达式,但构建单独的模式字符串可能更清晰。如果要替换的所有内容都是一个字符长,那么可以使用
'
连接,并使用字符类(例如
[\u^]
),而不是使用

连接,为什么不使用sub?@Toto:如果使用sub,我们可以减少替换行的长度吗?如果是,请告诉我详细的解决方法。@mwp:不是实体替换。这是一个内容查找和替换的过程。你给我们的例子肯定是实体替换,所以我觉得值得一提。:)为什么不用潜水艇?@Toto:如果我用潜水艇的话,我们可以减少替换的线路吗?如果是,请告诉我详细的解决方法。@mwp:不是实体替换。这是一个内容查找和替换的过程。你给我们的例子肯定是实体替换,所以我觉得值得一提。:)回答得很好。(我也会更改实体名称)回答得很好。(我还将更改实体名称)