Как удалить строку внутри строки, используя Perl с Regex? - PullRequest
2 голосов
/ 09 июля 2020

Итак, у меня есть несколько файлов XML, в которых есть лица с уникальными идентификаторами, и у каждого из них есть любимая еда (человек может быть в нескольких файлах xml):

Бывают случаи, когда человек с id = 300 может содержать food прямо в начале тега.

<person id="299">
    <food>
       <type> Hot Dog </type>
    </food>
</person>
<person id="300">
    <food>
       <type> Burger</type>
    </food>
</person>

Или могут быть другие теги перед тегом food

<person id="300">
    <year>
       <birth> 1990 </birth>
       <marriage> 2020 </marriage>
    </year>
    <food>
       <type> Vegan </type>
    </food>
</person>

Мне нужно использовать один Perl RegEx удаляет метки еды ТОЛЬКО тех людей, чей ID равен 300, независимо от того, находится ли он в начале, середине или конце тега человека

Я знаю, было ли это для тега целого человека Я мог бы использовать что-то вроде:

$fileContents =~ s/<person id=\"300\"[^<]+<\/person>//g;

Но я должен оставить тег человека нетронутым, я должен удалить только тег еды внутри тега человека, но я не могу удалить все теги еды, потому что мне нужно оставьте это людям с другими ID.

Не могли бы вы мне помочь ?? Я много боролся с этим D:

Ответы [ 2 ]

5 голосов
/ 09 июля 2020

Вы не можете безопасно сделать это с заменой.

И даже неполноценный подход сложнее, чем использование существующего парсера XML.

$_->unbindNode()
   for $doc->findnodes('//person[@id="300"]/food');

Полное решение :

use XML::LibXML qw( );

# my $doc = XML::LibXML->new->parse_file(...);
#    or
# my $doc = XML::LibXML->new->parse_string(...);

$_->unbindNode()
   for $doc->findnodes('//person[@id="300"]/food');

# $doc->toFile(...)
#    or
# $doc->toString(...)
1 голос
/ 11 июля 2020
perl -i.bk -pe'BEGIN{undef$/}s|<person (.*?)>.*?</person>|$p=$&;$1=~/id="300"/?$p=~s,<food>.*?</food>,,sr:$p|esg' files*.xml

... удаляет <food>.....</food> из лиц с id = "300" в одном или нескольких файлах *. xml. Исходные файлы сохраняются и переименовываются с добавлением .bk к их именам. Так что запускайте это только один раз, если вам нужно сохранить исходные файлы ... или замените -i.bk на, например, -i.bk$(date +%Y%m%d%h%M%S).

Примечание: я думаю, что ответ ikegami намного лучше.

Но иногда пишут perl для систем, не допускающих дополнительных модулей, а XML :: Lib XML, к сожалению, не является основным модулем. И иногда неполноценный XML может быть лучше / быстрее всего обработан неполноценными методами. Возможно, "XML" написано кем-то вне вашего контроля. Возможно, отсутствует узел root для списка лиц, как в первом примере здесь (список <person> s может быть окружен <list> ... </list>, чтобы сделать его читаемым XML: : Lib XML) Или с 'или "пропущены значения атрибутов, которые также не могут быть сразу прочитаны в XML :: Lib XML.

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