在单次拍摄中查找和替换两个变量中的相同字符

时间:2016-08-05 12:19:10

标签: regex perl

我想找到并替换多个存储内容的标量变量(每个字符串的内容会有所不同)因此我需要为两个变量插入两行来进行相同的替换。

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

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

是否有可能在一次拍摄/同时更换所有要更换的琴弦。请注意,内容会因字符串而异。 (可能是我问问题的方式是小孩,但是我正在替换超过200行,但试图减少编码行)

2 个答案:

答案 0 :(得分:6)

您可以将变量置于for循环中,该循环将依次为每个变量添加$_。请注意,下划线或分号都不需要在正则表达式模式中进行转义

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

然而,这两者都是非标准实体。你自己宣布过吗?你可能意味着caret而不是carrot,这是一种蔬菜!我看到它叫^,但我认为这也是非标准的。您始终可以使用^(和_作为下划线)

答案 1 :(得分:1)

最简单的方法可能是定义映射规则,从这些规则构建正则表达式,以及应用它们的提供函数。这是对它的抨击:

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。这可以防止映射键中的任何特殊字符影响正则表达式的行为。我也使用${\ .. }语法在s///中插入表达式,但是构建单独的模式字符串可能更清楚。如果您要替换的所有内容都是一个字符长,则可以加入''并使用字符类(例如[_^]),而不是加入|