我正在嘗試使用腳本自動化安裝過程。過程的一部分是尋找 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。
所以你有諸如//
遞歸查找之類的結構。
或//node[@name='test']
尋找:
<node name="test">content</node>
有一個方便的快速參考這提供了一種簡單的方法來了解如何使用 xpath 導航 XML。
答案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>