好吧,只需重写你得到的:
my @vars = qw ( backup_path work_path output_path );
for ( @{$config}{@vars} ) {
s,^/*,/,; #prefix
s,/*$,/,; #suffix
s,/+,/,g; #double slashes anywhere else.
}
我会谨慎 - 优化魔术正则表达式并不是在每种情况下都有优势,因为它们很快就会变得不可读。
以上使用哈希切片机制s///
从哈希中选择值(在本例中为引用),以及隐式操作的事实$_
。并在修改原始 var 时进行修改。
但是,如果您正在对包含/
切换分隔符的模式进行操作,那么了解它也很有用,因为这样您就不会得到“倾斜的牙签”效果。
s/\/{2,}/\//g
可以写成:
s,/+,/,g
或者
s|/{2,}|/|g
如果你想保留数字量词,因为+
它本质上是 1 或更多,它在这里的工作方式相同,因为它无论如何都会将一个 double 折叠成一个单一的,但它在技术上匹配/
(并用 替换它/
)原始模式不匹配。,
但是出于同样的原因,如果你的模式中有它,你不会想使用它。
但是我认为这可以解决问题;
s,(?:^/*|\b\/*$|/+),/,g for @{$config}{qw ( backup_path work_path output_path )};
这匹配一个交替分组,替换:
- 行首,零个或多个
/
- 字边界,零个或多个
/
行尾
- 其他任何地方的一个或多个斜线。
用一个/
.
如上所述使用哈希切片机制,但没有中间“vars”。
(由于某种原因,如果没有单词边界零宽度锚,第二个分组就无法正常工作\b
- 我认为这是一个回溯问题,但我不完全确定)
对于奖励积分 -如果您的源数据结构合适,您可能会选择@vars
使用:grep
my @vars = grep { /_path$/ } keys %$config;
#etc. Or inline with:
s,(?:^/*|\b\/*$|/+),/,g for @{$config}{grep { /_path$/ } keys %$config };
编辑:或如鲍罗丁所说:
s|(?:/|\A|\z)/*|/|
给我们:
#!/usr/bin/env perl
use strict;
use warnings;
use Data::Dumper;
my $config = {
backup_path => "/fish/",
work_path => "narf//zoit",
output_path => "/wibble",
test_path => 'home/datamonster//c2counts',
another_path => "/home/teledyne/tmp/",
again_path => 'home/////teledyne/tmp/',
this_path => '/var/backup/DOC/all_instruments/',
};
s,(?:/|\A|\b\z)/*,/,g for @{$config}{grep { /_path$/ } keys %$config };
print Dumper $config;
结果:
$VAR1 = {
'output_path' => '/wibble/',
'this_path' => '/var/backup/DOC/all_instruments/',
'backup_path' => '/fish/',
'work_path' => '/narf/zoit/',
'test_path' => '/home/datamonster/c2counts/',
'another_path' => '/home/teledyne/tmp/',
'again_path' => '/home/teledyne/tmp/'
};