Удалить определенные символы из группы регулярных выражений - PullRequest
2 голосов
/ 29 апреля 2019

У меня есть строка, которая выглядит следующим образом (ключ ": [" значение "," значение "," значение "])

"emailDomains":["google.co.uk","google.com","google.com","google.com","google.co.uk"]

и я использую следующее регулярное выражение для выбора из строки. (регулярное выражение настроено таким образом, что оно не выбирает строку, которая выглядит как этот «ключ»: [{«ключ»: «значение», «ключ»: «значение»}])

(?<=:\[").*?(?="])

Результирующий выбор:

google.co.uk","google.com","google.com","google.com","google.co.uk

Я хочу удалить "в этой строке выбора, и мне было интересно, есть ли простой способ сделать это с помощью команды замены. Желаемый результат ...

"emailDomains":["google.co.uk, google.com, google.com, google.com, google.co.uk"]

Как мне решить эту проблему?

Ответы [ 4 ]

4 голосов
/ 29 апреля 2019

Если ваша строка действительно имеет форму "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, чтобы быть возвращенным из всего этого куска кода в {} (сторона замены), чтобы использоваться в качестве замены.

1 голос
/ 29 апреля 2019

Вы можете использовать это регулярное выражение на основе \G, чтобы начать совпадение с :[", а затем соответствующим образом захватывает значения и заменяет сопоставленный текст, так что сохраняется только запятая и удаляются двойные кавычки.

(:\[")|(?!^)\G([^"]+)"(,)"

Regex Demo

1 голос
/ 29 апреля 2019

Ваш текст почти в правильном формате JSON, поэтому действительно легко пройти последний дюйм и сделать это так, а затем обработать это:

#!/usr/bin/perl
use warnings;
use strict;
use feature qw/say postderef/;
no warnings qw/experimental::postderef/;
use JSON::XS; # Install through your OS package manager or a CPAN client

my $str = q/"emailDomains":["google.co.uk","google.com","google.com","google.com","google.co.uk"]/;
my $json = JSON::XS->new();

my $obj = $json->decode("{$str}");
my $fixed = $json->ascii->encode({emailDomains =>
                                    join(', ', $obj->{'emailDomains'}->@*)});
$fixed =~ s/^\{|\}$//g;
say $fixed;
0 голосов
/ 29 апреля 2019

Попробуйте Regex: " *, *"

Замените на: ,

Демо

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...