изменить строку и удалить тег, используя perl из xml-файла?

У меня есть xml-файл (client_23.xml) в котором мне нужно изменить одну строку и удалить из нее один цельный тэг, поэтому я придумал скрипт perl:

В моем XML-файле у меня есть блок вроде этого. В моем xml-файле будет только один экземпляр <hello>collect_model = 1</hello> :

 <world> <hello>collect_model = 1</hello> <hello>enable_data = 0</hello> <hello>session_ms = 2*60*1000</hello> <hello>max_collect = string_integer($extract("max_collect"))</hello> <hello>max_collect = parenting(max_collect, max_collect, 1.0e99)</hello> <hello>output('{')</hello> </world> 

Мне нужно изменить эту строку так: <hello>collect_model = 0</hello> поэтому после изменения весь мой блок должен выглядеть следующим образом:

 <world> <hello>collect_model = 0</hello> <hello>enable_data = 0</hello> <hello>session_ms = 2*60*1000</hello> <hello>max_collect = string_integer($extract("max_collect"))</hello> <hello>max_collect = parenting(max_collect, max_collect, 1.0e99)</hello> <hello>output('{')</hello> </world> 

Во-вторых, мне нужно удалить весь тег из одного и того же XML-файла:

 <derta-config> <data-users>2000</data-users> <test-users>2000</test-users> <attributes>hello world</attributes> <client-types>Client1</model-types> <target>price.world</target> </derta-config> 

Таким образом, у меня есть сценарий оболочки, в котором я использую perl, который пытается сделать выше двух вещей наряду с заменой некоторого содержимого в файле (что я делаю для какой-то другой цели), но часть, которую я добавил специально для выше двух, не работа и он начинает печатать кучу ошибок:

 perl -0pe "s#<eval>collect_model = 0</eval>#<eval>collect_model = 1</eval> s#<derta-config>.* </derta-config>##sm; s#<function>\s*<name>DUMMY_FUNCTION.+?</function>#$file#sm" client_"$client_id".xml > "$word"_new_file.xml 

Поэтому я думаю, что мы можем сделать это в сценарии оболочки вместо этого, имея в виду remvoe из этих двух вещей, используя сценарий оболочки, а затем вывод этого, мы можем перейти к моему скрипту perl, который работает на третьем шаге. Итак, мы можем передать вывод сценария оболочки, который удалит эти две вещи для меня ниже этого скрипта perl? Возможно ли это сделать?

 perl -0pe "s#<function>\s*<name>DUMMY_FUNCTION.+?</function>#$file#sm" client_"$client_id".xml > "$word"_dyn_model.xml 

Здесь $client_id равно 23 а $word abc .

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

2 Solutions collect form web for “изменить строку и удалить тег, используя perl из xml-файла?”

С этим в качестве образца входного файла:

 $ cat client_23.xml <world> <hello>collect_model = 1</hello> <hello>enable_data = 0</hello> <hello>session_ms = 2*60*1000</hello> <hello>max_collect = string_integer($extract("max_collect"))</hello> <hello>max_collect = parenting(max_collect, max_collect, 1.0e99)</hello> <hello>output('{')</hello> </world> <derta-config> <data-users>2000</data-users> <test-users>2000</test-users> <attributes>hello world</attributes> <client-types>Client1</model-types> <target>price.world</target> </derta-config> 

Мы можем сделать оба изменения, используя:

 $ sed 's|<hello>collect_model = 1</hello>|<hello>collect_model = 0</hello>|; \|<derta-config>|,\|</derta-config>|d' client_23.xml <world> <hello>collect_model = 0</hello> <hello>enable_data = 0</hello> <hello>session_ms = 2*60*1000</hello> <hello>max_collect = string_integer($extract("max_collect"))</hello> <hello>max_collect = parenting(max_collect, max_collect, 1.0e99)</hello> <hello>output('{')</hello> </world> 

Как это работает

У нас есть две команды sed. Первая – это замена, вторая – удаление:

  • s|<hello>collect_model = 1</hello>|<hello>collect_model = 0</hello>|

    Заменяющие команды имеют форму s|old|new| , Итак, здесь old – это оригинальный <hello>collect_model = 1</hello> а new – это замена <hello>collect_model = 0</hello> .

  • \|<derta-config>|,\|</derta-config>|d

    Это определяет диапазон строк. Стартовая строка содержит derta-config> а конечная строка содержит </derta-config> . Все строки в этом диапазоне удаляются командой d удаления.

Пожалуйста, не используйте регулярное выражение для синтаксического анализа XML. Это плохая идея. Основная причина, по которой это плохая идея, состоит в том, что в XML есть много разнообразия, и некоторые семантически идентичные XML могут иметь несколько существенно различное сопоставление шаблонов.

Рассмотрим строки, пробелы, унарные теги и т. Д.

 <element /> <element></element> 

Оба одинаковые – и тогда вы можете отступать, переводить строки, разделить теги и т. Д .:

 <element att1="fish" att2="carrot"> 

Также является действительным.

Поэтому я настоятельно рекомендую «использовать парсер». У Perl есть несколько вариантов – мне нравится XML::Twig :

 #!/usr/bin/env perl use strict; use warnings; use XML::Twig; my $twig = XML::Twig->new( 'pretty_print' => 'indented_a' )->parse( \*DATA ); foreach my $hello ( $twig->findnodes('//hello') ) { if ( $hello->trimmed_text =~ m/collect_model/ ) { $hello->set_text('collect_model = 0'); } } $_->delete for $twig->findnodes('//derta-config'); $twig->print; __DATA__ <root> <world> <hello>collect_model = 1</hello> <hello>enable_data = 0</hello> <hello>session_ms = 2*60*1000</hello> <hello>max_collect = string_integer($extract("max_collect"))</hello> <hello>max_collect = parenting(max_collect, max_collect, 1.0e99)</hello> <hello>output('{')</hello> </world> <derta-config> <data-users>2000</data-users> <test-users>2000</test-users> <attributes>hello world</attributes> <client-types>Client1</client-types> <target>price.world</target> </derta-config> </root> 

Потому что вам, похоже, нравится однострочное в perl:

 perl -MXML::Twig -0777 -e 'my $twig = XML::Twig->parse (<>); $_->set_text("collect_model = 0") for grep { $_->text =~ m/collect_model/ } $twig->findnodes("//hello"); $_->delete for $twig->findnodes("//derta-config"); $twig -> print;' 
  • Замена XML на основе содержимого атрибута с помощью sed
  • Как использовать sed для извлечения из xml после сопоставления с шаблоном в одном из тегов внутри?
  • удалить что-нибудь между угловыми скобками, включая его
  • Разбирайте XML, чтобы получить значение узла в скрипте bash?
  • Удалить узел XML, содержащий определенный элемент
  • конвертировать xml в csv
  • sed на cygwin может заменить только одного персонажа?
  • Эффективное извлечение данных из нескольких файлов в один файл CSV
  • Используйте инструменты Unix для поиска блока определений в XML.
  • Найти соответствующие MD5 и XML в каталоге
  • строки в столбцы с awk
  • Interesting Posts

    Как использовать ssh-agent с несколькими (действительными) ключами и все же выбрать, какой из них использовать?

    Эквивалент для `dm-tool switch-to-user` otheruser в разных менеджерах отображения

    Как создать учетную запись пользователя root в Debian?

    Почему netconsole не ищет маршрут для ведения журнала сервера?

    Если оболочка запускает программу, будет ли оболочка также получать сигнал SIGINT при нажатии Ctrl + C?

    zsh: подстановка команды не наследует stdin из родительского

    выполнил «chmod 666 ld-2.17.so» – как мне восстановиться?

    Инструмент поиска с индексами содержимого файла

    Почему Ctrl-D (EOF) выходит из оболочки?

    Ошибка SIOCADDRT: нет такого процесса

    Отправка HTML с помощью mailx с postfix 2.6.6 и centOS 6.4

    Systemd.service: используйте функцию bash для настройки сети

    Как перезагрузить USB-устройство после безопасного извлечения?

    Как я могу искать имена файлов, которые начинаются с xy_ *, и создаются / редактируются сегодня?

    xmodmap для комбинации клавиш – как переключить поведение Fn?

    Linux и Unix - лучшая ОС в мире.