вставить слово в файл в зависимости от строки.

На самом деле это единственный раздел про unix на этом форуме

Модератор: /dev/random

zakachkin
Сообщения: 137

вставить слово в файл в зависимости от строки.

Сообщение zakachkin » 26.10.2015 13:40

Доброго дня уважаемые форумчане!
Не могли бы вы мне подсказать по сабжу, а именно:
В xml файле есть блоки информации:

Код: Выделить всё

<test>
        <url></url>
        <name></name>
        <Id>875</Id>
        <command>true</command>
        <pickup>false</pickup>
        <del></del>
        <model></model>
        <description></description>
</test>

таких блоков около 500
Подскажите пожалуйста, как мне взяв за переменную <Id>875</Id> добавить в секцию <model></model> значение которое присвоено этой переменной? в каждом блоке естественно.
зарание спасибо.
Спасибо сказали:

Аватара пользователя
Hephaestus
Сообщения: 2580
Статус: Многоуважаемый джинн...
ОС: Slackware64-14.1/14.2

Re: вставить слово в файл в зависимости от строки.

Сообщение Hephaestus » 26.10.2015 17:32

Наиболее правильный вариант - написать соответствующий xsl-файл.
И скормить это всё процессору вроде xsltproc.
По такой схеме происходит преобразование xml-файла.
На выходе можно получить как файл другого формата так и новый xml.
То есть, xsl и xml задумывались так, чтобы работать в паре.
Это действительно самый правильный вариант, но требует специальных знаний.
Если у Вас это не разовая задача, тогда имеет смысл это освоить.
Начать можно хотя бы отсюда.

Если же задача разовая, то можно попробовать обойтись другими средствами - sed, скрипты и пр.
Всё зависит от Вашего уровня подготовки.

Один из вариантов, реализуемый скриптом: приводим файл к виду, когда блок целиком в одной строке.
То есть добиваемся взаимно однозначного соответствия: одна строка - один блок.
Затем, действуем регулярными выражениями, поиском, заменой: ищем в строке нужный участок (открывающий и закрывающий тег), значение между тегами сохраняем в переменную, далее ищем целевой участок (опять-таки по тегам), заменой вставляем значение.
Пускай скрипят мои конечности.
Я - повелитель бесконечности...
Мой блог
Спасибо сказали:

Аватара пользователя
Hephaestus
Сообщения: 2580
Статус: Многоуважаемый джинн...
ОС: Slackware64-14.1/14.2

Re: вставить слово в файл в зависимости от строки.

Сообщение Hephaestus » 26.10.2015 21:33

Вариант с xsl-преобразованием может выглядеть примерно так

Исходный файл
Spoiler

test.xml

<?xml version="1.0"?> <document> <test> <url></url> <name></name> <Id>875</Id> <command>true</command> <pickup>false</pickup> <del></del> <model></model> <description></description> </test> <test> <url></url> <name></name> <Id>900</Id> <command>true</command> <pickup>false</pickup> <del></del> <model></model> <description></description> </test> <test> <url></url> <name></name> <Id>990</Id> <command>true</command> <pickup>false</pickup> <del></del> <model></model> <description></description> </test> </document>


Поскольку Вы привели лишь часть xml-файла, полная структура неизвестна.
В частности, повторяющийся элемент (<test>) не может быть корневым для xml-файла. Поэтому тег <document> добавлен мной для приведения xml-файла к корректному виду.

Файл преобразования
Spoiler

test.xsl

<?xml version="1.0"?> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> <xsl:output method="xml" indent="yes"/> <xsl:template match="/"> <xsl:apply-templates select="document"/> </xsl:template> <xsl:template match="document"> <document> <xsl:apply-templates select="test"/> </document> </xsl:template> <xsl:template match="test"> <test> <url> <xsl:apply-templates select="url"/> </url> <name> <xsl:apply-templates select="name"/> </name> <Id> <xsl:apply-templates select="Id"/> </Id> <command> <xsl:apply-templates select="command"/> </command> <pickup> <xsl:apply-templates select="pickup"/> </pickup> <del> <xsl:apply-templates select="del"/> </del> <model> <xsl:value-of select="Id"/> </model> <description> <xsl:apply-templates select="description"/> </description> </test> </xsl:template> </xsl:stylesheet>


В Вашем файле вместо тега <document>, будет другой и, вероятно, имеются ещё какие-то теги, поэтому файл преобразования для Вашей конкретной задачи будет отличаться. Но, думаю, общая идея ясна.

Команда преобразования

$

xsltproc text.xsl test.xml


Результат
Spoiler

'

<?xml version="1.0"?> <document> <test> <url/> <name/> <Id>875</Id> <command>true</command> <pickup>false</pickup> <del/> <model>875</model> <description/> </test> <test> <url/> <name/> <Id>900</Id> <command>true</command> <pickup>false</pickup> <del/> <model>900</model> <description/> </test> <test> <url/> <name/> <Id>990</Id> <command>true</command> <pickup>false</pickup> <del/> <model>990</model> <description/> </test> </document>


В рамках сформулированной задачи, практически то, что Вам нужно ;)
Пускай скрипят мои конечности.
Я - повелитель бесконечности...
Мой блог
Спасибо сказали:

Аватара пользователя
Bizdelnick
Модератор
Сообщения: 15819
Статус: grammatikführer
ОС: Debian GNU/Linux

Re: вставить слово в файл в зависимости от строки.

Сообщение Bizdelnick » 26.10.2015 22:52

Как по мне, вот так проще (воспользовался той же структурой документа, что привёл Hephaestus):

Код: Выделить всё

#!/usr/bin/perl

use strict;
use warnings;
use XML::Simple;

my $data = XMLin('test.xml', ForceArray => [ 'test' ]);

foreach my $test (@{ $data->{'test'} }) {
    $test->{'model'} = $test->{'Id'};
}

print XMLout($data, NoAttr => 1, RootName => 'document');

А парсить XML из шелла, чем Вы, как я понимаю, хотели заняться, крайне неблагодарное занятие.
Пишите правильно:
в консоли
вкупе (с чем-либо)
в общем
вообще
в течение (часа)
новичок
нюанс
по умолчанию
приемлемо
проблема
пробовать
трафик
Спасибо сказали:

Аватара пользователя
Hephaestus
Сообщения: 2580
Статус: Многоуважаемый джинн...
ОС: Slackware64-14.1/14.2

Re: вставить слово в файл в зависимости от строки.

Сообщение Hephaestus » 27.10.2015 07:16

Bizdelnick писал(а):
26.10.2015 22:52
Как по мне, вот так проще
Perl - мощная штука и Ваше решение красиво, бесспорно.
Но есть два обстоятельства:
Во-первых, как и в случае с моим решением, требуется наличие спец. знаний. Я, к примеру, просто не знал, что perl такое умеет.
Во-вторых, согласитесь, Ваше решение всё-таки одноразовое.
Даже при небольшом изменении структуры входного файла (или выходного, не важно), это будет по сути уже другой скрипт.
Вариант с xsl-преобразованием, на мой взгляд, потребует меньших изменений в шаблоне.
Поэтому, как я уже сказал выше, при регулярной работе с xml-файлами, лучше всё-таки освоить работу с xml/xsl.
ТС в этом смысле не обозначил никаких объемов, но что-то мне подсказывает, что это не случайный одиночный xml-файл.

Bizdelnick писал(а):
26.10.2015 22:52
А парсить XML из шелла, чем Вы, как я понимаю, хотели заняться, крайне неблагодарное занятие.
Ну, сойдет. При условии, что в арсенале нету спец. средств вроде xsl или того же perl.
Пускай скрипят мои конечности.
Я - повелитель бесконечности...
Мой блог
Спасибо сказали:

Аватара пользователя
Bizdelnick
Модератор
Сообщения: 15819
Статус: grammatikführer
ОС: Debian GNU/Linux

Re: вставить слово в файл в зависимости от строки.

Сообщение Bizdelnick » 27.10.2015 10:48

Hephaestus писал(а):
27.10.2015 07:16
Я, к примеру, просто не знал, что perl такое умеет.

Такое умеет не perl, а модуль XML::Simple. Аналогичное можно сделать на Python, если он ближе знаком, да и на многих других скриптовых (и не только) языках при наличии соответствующих библиотек.

Hephaestus писал(а):
27.10.2015 07:16
Во-вторых, согласитесь, Ваше решение всё-таки одноразовое.
Даже при небольшом изменении структуры входного файла (или выходного, не важно), это будет по сути уже другой скрипт.
Вариант с xsl-преобразованием, на мой взгляд, потребует меньших изменений в шаблоне.

Отнюдь. Если изменения структуры будут небольшие (например добавится какой-то элемент внутри <test>, или объявятся необязательные элементы), то никаких изменений в скрипте вообще не потребуется. А вот в XSL — потребуются.
Но вообще, конечно, куда приятнее работать с форматами, специально созданными для хранения структурированных данных, а не с приспособленным под эту задачу языком разметки текста, коим является XML. С ним слишком много неоднозначностей, для разрешения которых нужно указывать параметры типа ForceArray и NoAttr.
Пишите правильно:
в консоли
вкупе (с чем-либо)
в общем
вообще
в течение (часа)
новичок
нюанс
по умолчанию
приемлемо
проблема
пробовать
трафик
Спасибо сказали:

moshell
Сообщения: 27

Re: вставить слово в файл в зависимости от строки.

Сообщение moshell » 27.10.2015 21:57

Bizdelnick писал(а):
26.10.2015 22:52

Код: Выделить всё

#!/usr/bin/perl

use warnings;

попробуйте сократить до

Код: Выделить всё

#!/usr/bin/perl -w

мелоч, а прыятна
Спасибо сказали:

Аватара пользователя
Bizdelnick
Модератор
Сообщения: 15819
Статус: grammatikführer
ОС: Debian GNU/Linux

Re: вставить слово в файл в зависимости от строки.

Сообщение Bizdelnick » 27.10.2015 22:24

moshell писал(а):
27.10.2015 21:57
попробуйте сократить до

...однострока? Можно, конечно. Но только из-за любителей сокращать всё, что можно сократить, perl и недолюбливают. А если кому краткость родственница, то никто не мешает вообще выкинуть use strict и use warnings.
Пишите правильно:
в консоли
вкупе (с чем-либо)
в общем
вообще
в течение (часа)
новичок
нюанс
по умолчанию
приемлемо
проблема
пробовать
трафик
Спасибо сказали: