Измените текст в теге, но только тег содержится в определенном блоке 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 с использованием собственного анализатора намного безопаснее.

  • sed first n встречается в результате набора из двух тегов / паттернов
  • поиск точной строки в unix
  • Как синхронизировать 2 xml-файла?
  • Как добавить строку из списка в другой файл, когда указанная строка найдена?
  • Есть ли инструмент командной строки для проверки файлов RDF?
  • Переупорядочить текст в каждой строке файла
  • Как изменить значения в файле XML
  • Разделение файлов в Unix с использованием значений в файле
  • Создание сценария оболочки для записи в файл XML
  • Выделение пользовательского синтаксиса в Gedit
  • regex заменить текст в XML-файле в узле из командной строки
  • Interesting Posts

    Подключите beaglebone black, запуская Debian Image 2015-11-12 на ПК через Ethernet.

    Как автозапуск devilspie под gnome3 на Fedora 21?

    Как правильно использовать find с регулярным выражением?

    Проблема с вставкой новой строки между странными html-символами в html-файле – UTF-8

    Как избавиться от «сканирования файловых систем btrfs» при запуске?

    Как запретить пользователям переименование файлов при предоставлении разрешений на запись в Linux

    Преобразование определенного времени в конкретный часовой пояс времени в часовой пояс пользователя без использования даты GNU

    LFS-7.5 util-linux `make check` не работает

    Несоответствие версии pg_dump на Debian

    Вручную подключиться к точке доступа Wi-Fi (AP), несмотря на предварительно сконфигурированные точки доступа в wpa_supplicant

    Просмотр всех правил iptables

    нацеливание на конкретный блок с e2fsck для сокращения ожидания

    Неизвестная файловая система после копирования Debian ISO с dd

    Как принять переадресацию ICMP?

    Как я могу выполнить вывод tar через mv?

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