Измените текст в теге, но только тег содержится в определенном блоке XML

Используя Git Bash, я пытаюсь условно заменить то, что находится в теге yrot, в сотнях файлов, но только если оно принадлежит тегу имени части, который относится к колесу.

// YES, change <part name="D_wheel1" seqNumber="1" > <yrot min="0.000000" max="0.000000" cur="0.000000" /> </part> // YES, change <part name="D_wheel2" seqNumber="1" > <yrot min="0.000000" max="0.000000" cur="0.000000" /> </part> // NO, don't change <part name="door" seqNumber="1" > <yrot min="0.000000" max="0.000000" cur="0.000000" /> </part> // Example Line Change // From: <yrot min="0.000000" max="0.000000" cur="0.000000" /> // To: <yrot min="INF" max="INF"/> 

Возможно ли это с помощью awk? Или мне нужно использовать какой-то специальный синтаксический анализатор XML?

EDIT: Чтобы быть ясным, существует около десяти тегов, принадлежащих одному из них: a. отображается только в теге. Я хочу только заменить строку, если имя содержит «колесо». сам вложен.

Тем, кто утверждает, что мне нужен синтаксический анализатор XML, почему бы не просто найти или заменить текст, если условие выполнено (метка yrot находится в колесах)? Проверяет, что это так сложно?

4 Solutions collect form web for “Измените текст в теге, но только тег содержится в определенном блоке XML”

Использование стандартной библиотеки python ElementTree:

 #! /usr/bin/env python import sys import xml.etree.ElementTree as ET def do_one(file_name): tree = ET.parse(file_name) for part in tree.findall("part"): if not 'wheel' in part.attrib['name']: continue for yrot in part.findall('yrot'): names = [] for x in yrot.attrib: names.append(x) for x in names: del yrot.attrib[x] yrot.attrib['min'] = 'INF' yrot.attrib['max'] = 'INF' tree.write(file_name) for file_name in sys.argv[1:]: do_one(file_name) 

Это анализирует весь файл, переданный в командной строке, скрипту:

 python convert_xml.py *.xml 

Предоставлял свой XML в data.xml как:

  $ cat data.xml <?xml version="1.0" encoding="UTF-8"?> <root> <part name="D_wheel1" seqNumber="1"> <yrot min="0.000000" max="0.000000" cur="0.000000" /> </part> <part name="D_wheel2" seqNumber="1"> <yrot min="0.000000" max="0.000000" cur="0.000000" /> </part> <part name="door" seqNumber="1"> <yrot min="0.000000" max="0.000000" cur="0.000000" /> </part> </root> 

Использование xmlstarlet с XPath :

 $ xmlstarlet ed \ --var target '//part[contains(@name, "wheel")]/yrot' \ -u '$target/@*[name()="min" or name()="max"]' -v 'INF' \ -d '$target/@cur' data.xml <?xml version="1.0" encoding="UTF-8"?> <root> <part name="D_wheel1" seqNumber="1"> <yrot min="INF" max="INF"/> </part> <part name="D_wheel2" seqNumber="1"> <yrot min="INF" max="INF"/> </part> <part name="door" seqNumber="1"> <yrot min="0.000000" max="0.000000" cur="0.000000"/> </part> </root> 

Или классический подход с использованием XSLT : и xsltproc или xmlstarlet

 $ cat data.xsl <?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/> <xsl:template match="@*|node()"> <xsl:copy> <xsl:apply-templates select="@*|node()"/> </xsl:copy> </xsl:template> <xsl:template match="*[contains(@name, 'wheel')]/yrot"> <xsl:copy> <xsl:attribute name="min">INF</xsl:attribute> <xsl:attribute name="max">INF</xsl:attribute> </xsl:copy> </xsl:template> </xsl:stylesheet> $ xsltproc data.xsl data.xml #or: xmlstarlet tr data.xsl data.xml <?xml version="1.0" encoding="UTF-8"?> <root> <part name="D_wheel1" seqNumber="1"> <yrot min="INF" max="INF"/> </part> <part name="D_wheel2" seqNumber="1"> <yrot min="INF" max="INF"/> </part> <part name="door" seqNumber="1"> <yrot min="0.000000" max="0.000000" cur="0.000000"/> </part> </root> 

Существует серьезная проблема с попыткой разобрать XML с помощью стандартных инструментов unix. XML – это структура данных и поддерживает множество макетов, которые семантически идентичны, но не имеют одинаковых строк и отступов.

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

Поэтому да, пожалуйста, используйте синтаксический анализатор XML. Существует множество вариантов: кто-то дал вам опцию python, поэтому я тоже включил perl.

 #!/usr/bin/perl use strict; use warnings; use XML::Twig; sub process_part { my ( $twig, $part ) = @_; if ( $part->att('name') =~ m/wheel/ ) { $part->first_child('yrot')->set_att( 'min', 'INF' ); $part->first_child('yrot')->set_att( 'max', 'INF' ); } } my $twig = XML::Twig->new( 'pretty_print' => 'indented_a', 'twig_handlers' => { 'part' => \&process_part } ); $twig->parsefile('your_file.xml'); $twig->print; 

Теперь, по причине «проверки» вашего текста является diffcult – все они одинаковы:

 <root> <part name="D_wheel1" seqNumber="1"> <yrot cur="0.000000" max="0.000000" min="0.000000" /> </part> <part name="D_wheel2" seqNumber="1"> <yrot cur="0.000000" max="0.000000" min="0.000000" /> </part> <part name="door" seqNumber="1"> <yrot cur="0.000000" max="0.000000" min="0.000000" /> </part> </root> 

А также:

 <root><part name="D_wheel1" seqNumber="1"><yrot cur="0.000000" max="0.000000" min="0.000000"/></part><part name="D_wheel2" seqNumber="1"><yrot cur="0.000000" max="0.000000" min="0.000000"/></part><part name="door" seqNumber="1"><yrot cur="0.000000" max="0.000000" min="0.000000"/></part></root> 

А также:

 <root ><part name="D_wheel1" seqNumber="1" ><yrot cur="0.000000" max="0.000000" min="0.000000" /></part><part name="D_wheel2" seqNumber="1" ><yrot cur="0.000000" max="0.000000" min="0.000000" /></part><part name="door" seqNumber="1" ><yrot cur="0.000000" max="0.000000" min="0.000000" /></part></root> 

Они все семантически идентичны, но, надеюсь, как вы можете видеть – не будут разбирать то же самое. Такие вещи, как унарные метки – например,

  <yrot cur="0.000000" max="0.000000" min="0.000000" /> 

Vs:

  <yrot cur="0.000000" max="0.000000" min="0.000000" ></yrot> 

Также – семантически идентичны. Таким образом, вы можете уйти с линейным и регулярным выражением, но он принимает азартные игры и строит хрупкий код.

Использование awk. Обратите внимание, что это предполагает очень простую файловую структуру, подобную той, которую вы показываете. Я не могу гарантировать, что он будет работать на произвольных XLM-файлах. На самом деле, я могу отказаться от гарантии, что этого не произойдет.

 awk '{if(/<\/part>/){p=0}if($1~/<part/ && $2~/wheel/){p=1} if(p==1 && /<yrot/){ print "<yrot min=\"INF\" max=\"INF\"/>" } else{print}}' file 

Серьезно, хотя, это так же хрупко, как может быть. Он предполагает, что name= всегда является полем с разделителем 2-го пространства на линии, оно разбивается на вложенные теги и всевозможные другие возможные осложнения. Он дает желаемый результат в примере, который вы дали, но он будет разбиваться на самые незначительные изменения, внесенные вами в файлы. Подход Anthon с использованием собственного анализатора намного безопаснее.

  • Обновление значения XML с помощью xmlstarlet
  • awk: разобрать и записать в другой файл
  • Эффективное извлечение данных из нескольких файлов в один файл CSV
  • Добавьте содержимое файла XML другому, используя скрипт bash
  • создать файл XML с помощью сценария bash
  • Ошибка синтаксиса Openbox в ~ / .config / openbox / rc.xml
  • Добавление нового атрибута в существующий xml-файл с помощью sed или awk
  • Удалить узел XML, содержащий определенный элемент
  • изменить строку и удалить тег, используя perl из xml-файла?
  • Удалить строку с пробелами и цитатами из xml-файла
  • Вставка текста между двумя шаблонами
  • Interesting Posts

    Таймаут при установке EFS на EC2

    О взаимосвязи между инициализацией оболочки и настольными приложениями после «графического входа»

    Какова цель avahi на сервере RHEL 7?

    POST json данные с cURL из цикла while – bash shell

    Заменить пробелы символами подчеркивания в файлах: Ошибка в моем сценарии bash

    Предоставляет ли разрешение на запись для файлов журналов определенным пользователям хорошую практику?

    rsync «нет такого файла или каталога» при использовании шаблона

    тонко подготовленный корневой раздел в Centos 7

    Запуск X на другой видеокарте

    Создание сетевых конфигурационных файлов с помощью sed и bash

    Как настроить `sudo yum install …` инструкции по установке пакетов под `$ HOME / .hostdir` без привилегий суперпользователя?

    Понимать этот вывод strace

    Запуск скрипта каждые 15 минут 9-4 с использованием Systemd.timer

    Как изменить пароль root на Debian?

    Как сканировать и сравнивать два файла, которые будут соответствовать IP-адресам? Сценарий для веб-хостинга

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