Я пытаюсь автоматизировать процесс установки с помощью скрипта. Часть процесса заключается в поиске определенных разделов XML-файла конфигурации (см. ниже) и изменении определенных параметров с false
на true
или наоборот.
В файле конфигурации есть много разделов, которые имеют <enabled>
тег (в данном случае это <ssh>
раздел). Итак, мой вопрос в том, как мне найти конкретный <enabled>
тег и изменить его?
<ssh>
<enabled>true</enabled>
<ip>0.0.0.0</ip>
<port>2024</port>
</ssh>
решение1
Вы не привели достаточно большой пример XML, поэтому мне остается лишь немного догадываться.
Я бы предположил, что инструментом для этой работы будет приличный XML-парсер и Perl.
Я настоятельно рекомендую вам НЕ использовать:
Потому что оба варианта хрупкие — они работают в контролируемых условиях, но у вас есть хакерский, опасный код, который может по непонятной причине сломаться в один прекрасный день.
Вместо этого используйте синтаксический анализатор, который поддерживает xpath
XML, что является способом поиска/выбора нужного вам контента и его изменения.
Что-то вроде этого XML::Twig
имеет низкий порог входа. (XML::LibXML также является хорошей альтернативой, но гораздо более исчерпывающей).
#!/usr/bin/env perl
use strict;
use warnings;
use XML::Twig;
#parse the content - you probably want `parsefile` here instead.
my $twig = XML::Twig -> new ( pretty_print => 'indented_a' ) -> parse ( \*DATA );
#select the node you want, alter it.
$twig -> get_xpath('./ssh/enabled',0) -> set_text('false');
#print the output (to STDOUT) - you can print {$output_fh} $twig->sprint; instead
$twig -> print;
__DATA__
<xml>
<www>
<enabled>true</enabled>
<ip>0.0.0.0</ip>
<port>80</port>
</www>
<ssh>
<enabled>true</enabled>
<ip>0.0.0.0</ip>
<port>2024</port>
</ssh>
<smtp>
<enabled>true</enabled>
<ip>0.0.0.0</ip>
<port>25</port>
</smtp>
</xml>
Примечание - get_xpath
использует формат типа "структура каталогов". Он поддерживает абсолютные пути в XML, а также относительные пути. При выполнении вышеописанного способа он будет работать с первым элементом, соответствующим этому пути (XML допускает несколько).
Однако вы можете сделать это в цикле foreach:
foreach my $thing ( $twig -> get_xpath ('//enabled') ) {
$thing -> set_text('false');
}
чтобы отключить все.
xpath
довольно гибкий - это способ указания пути, элемента и атрибутов иидеально подходитдля навигации по XML с использованием регулярных выражений.
Итак, у вас есть такие конструкции, как //
for find recursive.
Или //node[@name='test']
найти:
<node name="test">content</node>
Естьудобный краткий справочникЭто дает простой способ увидеть, как перемещаться по XML с помощью XPath.
решение2
Поскольку несколько узлов в вашем файле конфигурации имеют дочерние узлы с одинаковым именем, я бы рекомендовал писать ваш скрипт таким образом, чтобы он действительно понимал формат XML. Вот пример Perl для изменения двух ваших элементов конфигурации:
#!/usr/bin/perl
use strict;
use warnings;
use XML::Simple;
my $config = 'config.xml';
my $xml = XMLin($config, KeepRoot => 1, ForceArray => 1,);
$xml->{config}->[0]->{ssh}->[0]->{enabled} = 'false';
$xml->{config}->[0]->{web}->[0]->{ip} = '127.0.0.1';
XMLout($xml, KeepRoot => 1, NoAttr => 1, OutputFile => $config,);
Вот мой вклад config.xml
:
<config>
<ssh>
<enabled>true</enabled>
<ip>0.0.0.0</ip>
<port>2024</port>
</ssh>
<web>
<enabled>true</enabled>
<ip>0.0.0.0</ip>
<port>80</port>
</web>
</config>
И вот что получилось:
<config>
<ssh>
<enabled>false</enabled>
<ip>0.0.0.0</ip>
<port>2024</port>
</ssh>
<web>
<enabled>true</enabled>
<ip>127.0.0.1</ip>
<port>80</port>
</web>
</config>