我很困惑,使用shell脚本设置XML的标记值(Value可能包含特殊字符)。
XML标记值应该是双引号。
要求: 我有一个带有标签值的xml。对于shell脚本,我必须添加一个带有值的新XML标签 在标签之前。 所以我正在使用sed,我尝试如下。如果$ 4 $ 5没有特殊字符,这可以正常工作。如何使用特殊字符进行此工作?(例如:&><:"。,;& #39;等)
sed '/<jobResulsDir/s/<jobResulsDir/<CommCellUser userName="'$4'" password="'$5'" > <\/CommCellUser> '$test' <jobResulsDir /' $temp_dir/PreImageModeFile.xml > $temp_dir/PreImageModeFile2.xml
除了sed还有其他方法。请帮助我
答案 0 :(得分:0)
为什么不使用perl?它必须是一个shell脚本。
#!/usr/bin/perl
use XML::Simple;
use Data::Dumper;
open(my $XML_IN, '<', '/xml/file/path.xml');
$/=undef;
my $xml_ref = XMLIn(<$XML_IN>);
print Dumper \$xml_ref;
# ... access $xml_ref in appropriate location, adding element / value
my $new_xml = XMLout($xml_ref);
close $XML_IN;
open(my $XML_OUT, '>', '/xml/file/path.xml');
print $XML_OUT $new_xml;
close $XML_OUT;
答案 1 :(得分:0)
你试图用sed做什么会撕掉你的大脑,你必须在每个特殊角色之前使用反斜杠才能让它运转起来。我用m4做这种工作。观看一个例子:
define(your_macro_name,<Delete>
<Object fdn="SubNetwork=somemoredata`,SubNetwork=somedata'`,ManagedElement'=$1"/>
</Delete>)dnl
将上述代码保存在名为“xmlmacros.m4”的文件中 然后创建一个名为“test.m4”的文件并添加以下内容:
include(xmlmacros.m4)dnl
your_macro_name(YOURXMLVALUE)
如果这两个文件位于同一个文件夹中,则可以运行m4 test.m4
,输出将为:
<Delete>
<Object fdn="SubNetwork=somemoredata,SubNetwork=somedata,ManagedElement=YOURXMLVALUE"/>
其中$1
将替换为“test.m4”文件括号中的值。您还可以添加更多定义,按需创建xml文件,例如xml标题等。
以上是您可以使用的工作示例。您可以浏览一下有关m4的更多信息,我总是将它用于此类工作。
答案 2 :(得分:0)
Awk并不关心“特殊字符”。这在sed:
sed '/<jobResulsDir/s/<jobResulsDir/<CommCellUser userName="'$4'" password="'$5'" > <\/CommCellUser> '$test' <jobResulsDir /'
这是awk:
awk -v userName="$4" -v password="$5" -v test="$test" '
/<jobResulsDir/{ sub(/<jobResulsDir/, "<CommCellUser userName=" userName " password=" password " </CommCellUser> " test " <jobResulsDir ") }
{ print }
'
但您实际上并不需要预先测试/<jobResulsDir/
,因为只有RE存在才会出现sub(),因此您可以将其缩写为:
awk -v userName="$4" -v password="$5" -v test="$test" '
{ sub(/<jobResulsDir/, "<CommCellUser userName=" userName " password=" password " </CommCellUser> " test " <jobResulsDir "); print }
'
不确定这是否是您的评论/问题,但如果您需要围绕值名称使用双引号,只需调整脚本以便在需要的地方提供:
awk -v userName="$4" -v password="$5" -v test="$test" '
{ sub(/<jobResulsDir/, "<CommCellUser userName=\"" userName "\" password=\"" password "\" </CommCellUser> \"" test "\" <jobResulsDir "); print }
'
最后,如果您愿意,可以通过以下方式将工作分解为更具可读性和效率:
awk -v userName="$4" -v password="$5" -v test="$test" '
BEGIN{
q = "\""
rep = \
"<CommCellUser userName=" q userName q\
" password=" q password q\
" </CommCellUser> " q test q\
" <jobResulsDir "
}
{ sub(/<jobResulsDir/, rep); print }
'
看着它的方式,我意识到我撒谎了一点关于awk不关心“特殊人物”。 sub()实际上关心1“特殊字符”,那是“&amp;”在替换字符串中,因为它用于反向引用sub()中匹配的内容,因此您需要在rep中用“\&amp;”替换“&amp;”s:
awk -v userName="$4" -v password="$5" -v test="$test" '
BEGIN{
q = "\""
rep = \
"<CommCellUser userName=" q userName q\
" password=" q password q\
" </CommCellUser> " q test q\
" <jobResulsDir "
}
{ gsub(/&/,"\\\\&",rep); sub(/<jobResulsDir/, rep); print }
它需要4“\”,因为字符串文字在awk中被解释两次(一次解释脚本时再次执行),而不是\得到文字反斜杠,你需要\\。
如果您愿意,还有一种使用match()和substr()的替代方法没有该约束:
awk -v userName="$4" -v password="$5" -v test="$test" '
BEGIN{
q = "\""
rep = \
"<CommCellUser userName=" q userName q\
" password=" q password q\
" </CommCellUser> " q test q\
" <jobResulsDir "
}
match($0,/<jobResulsDir/) {
$0 = substr($0,1,RSTART) rep substr($0,RSTART+RLENGTH)
}
{ print }
'
就个人而言,我会选择match()/ substr()方法,因为我讨厌使用转义字符。
只是为了循环回到我们开始的地方,如果你愿意的话,你可以把它写成一个单行:
awk -v userName="$4" -v password="$5" -v test="$test" '{
print (match($0,/<jobResulsDir/) ? substr($0,1,RSTART) "<CommCellUser userName=\"" userName "\"password=\"" password "\" </CommCellUser> \"" test "\" <jobResulsDir " substr($0,RSTART+RLENGTH) : $0)
}'