我有一个具有以下结构的XML文件:
<user-mapping>
<authorize username="user2" password="asdasdsss" >
<connection name="U2 - Windows 7 ">
<protocol>rdp</protocol>
<param name="hostname">192.168.203.2</param>
<param name="port">21122</param>
<param name="password">asdasdsss</param>
<param name="username">user</param>
</connection>
<connection name="U2 - Windows XP SP3 ">
<protocol>rdp</protocol>
<param name="hostname">192.168.203.2</param>
<param name="port">21120</param>
<param name="password">asdasdsss</param>
<param name="username">user</param>
</connection>
</authorize>
</user-mapping>
此文件包含大约20个用户(authorize
元素),每个用户有大约15个计算机连接。
我创建了一个Perl程序来仅更改密码字段,但它基于计算行和字符,直到找到该字段。如果我添加其他param
元素,则必须修改脚本。
我希望有一种动态的doit方式,以便Perl可以选择正确的用户节点并更改所有相关计算机中的密码字段。我尝试了很多方法,但我无法让它发挥作用。
应为用户和所有计算机更改密码。它们都将被更改为相同的密码
我现在使用的代码:
open( FILL, "< /etc/user-mapping.xml" );
@strings = <FILL>;
$i = 0;
foreach $line (@strings) {
print $i;
print $line;
$i++;
}
print "Number: ";
print $set_id;
$set_id = $set_id - 2;
$set_id = $set_id * 102;
print "Line: ";
print $set_id;
substr( @strings[ 1 + $set_id ], 43, 9 ) = "$password";
substr( @strings[ 6 + $set_id ], 39, 9 ) = "$password";
substr( @strings[ 13 + $set_id ], 39, 9 ) = "$password";
foreach $line ( @strings ) {
print $i;
print $line;
$i++;
}
open( FH, "> /etc/user-mapping.xml" );
foreach $line (@strings) {
print( FH $line );
}
close(FH);
close(FILL);
答案 0 :(得分:3)
我希望您明白将密码保存为纯文本是一个非常糟糕的主意吗?
您必须使用正确的XML解析器,我建议您使用XML::Twig
,因为它比某些替代方案更友好
这是一个按照你的要求做的程序。它会将密码更改为abc123
。如您所见,它甚至比原始程序还要短
它使用XPath表达式查找文档中的所有/user-mapping/authorize
元素,并将其密码属性更改为新密码。然后,它会查找每个connection/param
元素中具有authorize
属性的每个name="password"
元素,并更改其中的文本值
use strict;
use warnings 'all';
use XML::Twig;
use constant XML_FILE => 'user-mapping.xml';
use constant NEW_PASSWORD => 'abc123';
use constant USER_NAME => 'user2';
my $twig = XML::Twig->new;
$twig->parsefile(XML_FILE);
for my $auth ( $twig->findnodes('/user-mapping/authorize') ) {
next unless $auth->att('username') eq USER_NAME;
$auth->set_att(password => NEW_PASSWORD);
for my $pass ( $auth->findnodes('connection/param[@name="password"]') ) {
$pass->set_text(NEW_PASSWORD);
}
}
$twig->set_pretty_print('indented');
$twig->print;
<user-mapping>
<authorize password="abc123" username="user2">
<connection name="U2 - Windows 7 ">
<protocol>rdp</protocol>
<param name="hostname">192.168.203.2</param>
<param name="port">21122</param>
<param name="password">abc123</param>
<param name="username">user</param>
</connection>
<connection name="U2 - Windows XP SP3 ">
<protocol>rdp</protocol>
<param name="hostname">192.168.203.2</param>
<param name="port">21120</param>
<param name="password">abc123</param>
<param name="username">user</param>
</connection>
</authorize>
</user-mapping>
答案 1 :(得分:1)
使用真正的XML解析器。例如,使用XMLStarlet,这将非常简单:
xmlstarlet ed \
-u '//authorize/@password' -v "new-password" \
-u '//connection/param[@name="password"]' -v "new-password"