Хотя я думаю, что подстановка регулярных выражений не совсем идеальное решение (похоже, вместо этого оно должно быть исправлено должным образом), вот удобный способ решить эту проблему с помощью chomp
.
use Data::Dumper;
my %a = (
foo => {
a => "foo\x00",
b => "foo\x00"
},
bar => {
c => "foo\x00",
d => "foo\x00"
},
baz => {
a => "foo\x00",
a => "foo\x00"
}
);
$Data::Dumper::Useqq=1;
print Dumper \%a;
{
local $/ = "\x00";
chomp %$_ for values %a;
}
print Dumper \%a;
chomp
удалит одно конечное значение, равное тому, для которого установлен разделитель входных записей $/
.При использовании в хэше значения будут сжаты.
Как вы заметите, нам не нужно использовать значения напрямую, поскольку они являются псевдонимами.Также обратите внимание на использование блока вокруг оператора local $/
для ограничения его области действия.
Для более управляемого решения, вероятно, лучше создать подпрограмму, которая вызывается рекурсивно.Я снова использовал chomp
, но вы можете просто пропустить это и использовать s/\x00//g
.Или tr/\x00//d
, который в основном делает то же самое.chomp
безопаснее только потому, что удаляет только символы из конца строки, как s/\x00$//
.
strip_null(\%a);
print Dumper \%a;
sub strip_null {
local $/ = "\x00";
my $ref = shift;
for (values %$ref) {
if (ref eq 'HASH') {
strip_null($_); # recursive strip
} else {
chomp;
}
}
}