Добавить / удалить строку в соответствии с шаблоном - PullRequest
0 голосов
/ 20 марта 2019

Мне нужно найти список на основе шаблона и добавить или удалить другую строку ...

У меня есть список URL-адресов в файле XML.

В моем файлев одной строке у меня есть это:

"xml" : "SOMESTUFFWEDONOTCARE<node n=\"Group1\" u-l=\"toto.com;tata.com;tutu.com\"></node><node n=\"Group2\" u-l=\"bobo.com;baba.com\"></node><node n=\"Group3\" u-l=\"toto.com;papa.com;pepe.com;pupu.com\"></node>SOMESTUFFWEDONOTCARE"

Мои вопросы:

  1. в группе 1 Я хочу добавить "newwebsite.com" в свой список (в конце моегоlist)

Итак, u-l=\"toto.com;tata.com;tutu.com\" становится u-l=\"toto.com;tata.com;tutu.com;newwebsite.com\"

Конечно, я знаю только "Group1" и "newwebsite.com" ...

в группе 3 Я хочу удалить «toto.com» из моего списка

Так что u-l=\"toto.com;papa.com;pepe.com;pupu.com\" становится u-l=\"papa.com;pepe.com;pupu.com\"

Он не должен удалять «toto.com» изGroup1, и я предполагаю, что я не знаю, где находится «toto.com» в моем списке Group3 (возможны позиции от 1 до N).

Решением может быть код на Perl (работа с файлом в качестве обработчика файлов) или "sed" в коде perl (работа с файлом напрямую).Я не хочу помещать xml в хеш и работать с ним (я пробовал, и в основном это работает, но когда мы снова помещаем все в файл, это беспорядок из-за акцентированных символов, новых строк или не utf-8символов, вывод никогда не совпадает с вводом ...

Ответы [ 3 ]

1 голос
/ 20 марта 2019

Это можно сделать просто с помощью анализа JSON.Я сомневаюсь, что это хорошая идея сделать это вообще без анализа JSON.

Я написал реализацию, которая может модифицировать группы, добавлять, а также удалять домены из них.Вы должны иметь в виду, что изменение содержимого в XML с помощью регулярных выражений всегда неубедительно и наивно.Он легко сломается, поскольку полагается на то, что все находится в правильном порядке.Он не знает об атрибутах внутри тегов XML или даже самих тегах.Это просто куча текста.

Сказав это, давайте сначала посмотрим на конфигурацию и фактический вызов.

use strict;
use warnings;
use JSON;
my $json =
  q[{"xml" :"SOMESTUFFWEDONOTCARE<node n=\"Group1\" u-l=\"toto.com;tata.com;tutu.com\"></node><node n=\"Group2\" u-l=\"bobo.com;baba.com\"></node><node n=\"Group3\" u-l=\"toto.com;papa.com;pepe.com;pupu.com\"></node>SOMESTUFFWEDONOTCARE"}];
my $hash = decode_json $json;
$hash->{xml} = process(
    $hash->{xml} => {
        "Group1" => {add    => [qw/newwebsite.com/]},
        "Group3" => {remove => [qw/toto.com/]}
    },
);
print encode_json($hash);

Первое предположение состоит в том, что строка данных, которую вы далиНас, который выглядит как JSON, на самом деле является JSON, и что экранирование с обратными слешами является дословным.Если это изменится, весь код нарушится.

Здесь есть конфигурация, которая позволяет вам сказать, что вы хотите add и / или remove домены из группы.

Это сделано вprocess sub, который будет перебирать группы, находит первое вхождение в строке XML и обрабатывает его.Это предполагает, что весь документ XML находится в одной строке.Если есть новые строки, это прерывается.

Вот полная функция.

sub process {
    my ($xml, $args) = @_;

    foreach my $group (keys %$args) {
        if ($xml =~ m/<node n="\Q$group\E" u-l="([^"]+)">/) {
            my $existing_list = $1;
            my @items = split /;/, $existing_list;

            # remove items from the list
            if (exists $args->{$group}->{remove}) {
                no warnings 'experimental';

                my @remove = @{$args->{$group}->{remove}};
                @items = grep { not $_ ~~ @remove } @items;
            }

            # add new items to the list
            if (exists $args->{$group}->{add}) {
                push @items, @{$args->{$group}->{add}};
            }

            # serialise the list and stick it back in
            # need the "" as an anchor
            my $new_list = join ';', @items;
            $xml =~ s/"(\Q$existing_list\E)"/"$new_list"/;
        }
    }
    return $xml;
}

Помните, что, хотя это выглядит как XML, мы воспринимаем его как просто текст.Нам нужен открывающий и закрывающий кронштейн <node> в качестве якоря.Мы берем список доменов и манипулируем им.Если есть лишние пробелы или порядок элементов изменяется, это нарушается.

Код использует простые операции со списками для обработки списков доменов.

Чтобы разрешить легкое удаление нескольких доменов, это используетэкспериментальный оператор smartmatch.Вы можете реализовать это по-другому, но мне было лень.Он будет работать только на определенной версии Perl, поскольку это экспериментально.

Затем мы вставляем новый список обратно в большую строку, которая выглядит как XML, заменяя старую.Нам нужно убедиться, что никакие специальные символы (например, точка .) не попадают в шаблон, поэтому мы избегаем его с помощью \Q и \E.

В случае, если это еще не ясно, я будускажи это снова.Хотя это работает для этого очень специфического набора параметров, который вы задали в своем вопросе, скорее всего, это не будет работать в полной мере для вас.Вам придется адаптировать его, и, вероятно, адаптировать его часто.

Возможно, вам лучше использовать как JSON-анализатор, так и XML-анализатор.

0 голосов
/ 08 апреля 2019

от gnu sed, ваша строка данных в файле 'd'

sed -E 's/(Group1\\.[^>]+)\"(><)/\1;newwebsite.com"\2/i; s/(Group3\\"[^=]+=\\")toto\.com;/\1/i' d
0 голосов
/ 20 марта 2019

Я считаю, что это работает.Я использую методы подстановки регулярных выражений perl.Надеюсь, я не правильно понял вопрос.

my $line = '"xml" : "SOMESTUFFWEDONOTCARE<node n=\"Group1\" u-l=\"toto.com;tata.com;tutu.com\"></node><node n=\"Group2\" u-l=\"bobo.com;baba.com\"></node><node n=\"Group3\" u-l=\"toto.com;papa.com;pepe.com;pupu.com\"></node>SOMESTUFFWEDONOTCARE"';

my $new_word = "newwebsite.com";
my $remove_word = "toto.com";
print $line;
$line =~ s/(.+)\\\"(Group1\\\" u-l=\\\".+.com)(\\\"\>\<\/node\>\<node n=\\\"Group2.+)(Group3\\\" u-l=\\\".+.com)(.+)/$1.$2.';'.${new_word}.$3.'***'.rm_string($4,$remove_word).$5/e;
print("\n\n$line");


sub rm_string{
    $string = shift;
    $remove_string=shift;
    $string =~ s/$remove_string;?//;
    $string =~ s/;$//;
    return($string);

}

результат дает после подстановки-


"xml" : "SOMESTUFFWEDONOTCARE<node n=Group1\" u-l=\"toto.com;tata.com;tutu.com;newwebsite.com\"></node><node n=\"Group2\" u-l=\"bobo.com;baba.com\"></node><node n=\"***Group3\" u-l=\"papa.com;pepe.com;pupu.com\"></node>SOMESTUFFWEDONOTCARE"

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