Если ваша строка действительно имеет форму "key":["v1", "v2", ... "vN"]
, вы можете отделить часть, которую необходимо изменить, заменить ","
пробелом в ней и заново собрать:
my @parts = split / (\["\s* | \s*\"]) /x, $string; #"
$parts[2] =~ s/",\s*"/ /g;
my $processed = join '', @parts;
Шаблон регулярного выражения для разделителя в split
фиксируется, поскольку в этом случае разделители также находятся в возвращаемом списке, что здесь полезно для объединения строки обратно.Затем нам нужно изменить третий элемент массива.
В этом подходе мы должны изменить конкретный элемент в массиве, поэтому, если ваш формат меняется, даже немного, это может не произойти (или все еще может) быть подходящим.
Это, конечно, должно обрабатываться как JSON с использованием модуля.Если формат не уверен, как указано в комментарии, было бы лучше убедиться, что у вас есть JSON.Сбор фрагментов, как указано выше (или ниже), - это путь к безумию, когда требования постепенно начинают развиваться.
Тот же самый подход может быть использован в регулярном выражении, и на самом деле это может иметь преимущество:возможность отобрать и проигнорировать все, что предшествует :
(с split
эта часть может закончиться несколькими элементами, если формат не совсем такой, как показано, что затем влияет на все)
$string =~ s{ :\["\s*\K (.*?) ( "\] ) }{
my $e = $2;
my $n = $1 =~ s/",\s*"/ /gr;
$n.$e
}ex;
ЗдесьМодификатор /e
делает так, чтобы сторона замены оценивалась как код, где мы делаем то же самое, что и с split
выше.Примечания к регулярному выражению
Сначала нужно сохранить $2
, так как он будет сброшен в следующем регулярном выражении
Модификатор /r
† , который не меняет свою цель, а скорее возвращает измененную строку, это то, что позволяет нам использовать оператор подстановки только для чтения $1
Еслиничего не захватывается для $2
, а возможно и для $1
, это означает, что не было совпадений, и в результате просто $string
не меняется, тихо .Так что если эта замена должна всегда работать, то вы можете добавить обработку таких неожиданных данных
Не нужно $n
выше, но может вернуть ($1 =~ s/",\s*"/ /gr) . $e
Или, если попытаться использовать обходные пути
$string =~ s{ (?<=:\[") (.+?) (?="\]) }{ $1 =~ s/",\s*"/ /gr }egx;
, что сокращает объем кода, но может быть сложнее работать позже.
Хотя этопрямой ответ на вопрос, я думаю, что это наименее ремонтопригодно.
† Этот полезный модификатор "неразрушающего замещения" появился в v5.14.В более ранних версиях Perl мы копировали строку и выполняли для нее регулярное выражение с идиомой
(my $n = $1) =~ s/",\s*"/ /g;
В примере с lookarounds нам понадобится немного больше
$string =~ s{...}{ (my $n = $1) =~ s/",\s*"/ /g; $n }gr
, начиная с s/
оператор возвращает количество выполненных замен, в то время как нам нужно $n
, чтобы быть возвращенным из всего этого куска кода в {}
(сторона замены), чтобы использоваться в качестве замены.