我有一个XML文件,其中包含以下行:
<VALUE DECIMAL_VALUE="0.2725" UNIT_TYPE="percent"/>
我想将此值增加.04并保持XML的格式。我知道这可以使用Perl或awk脚本,但是我很难用表达式来隔离数字。
答案 0 :(得分:4)
如果你在xsltproc命令的盒子上,我建议你使用XSLT。
对于Perl解决方案,我会选择使用DOM。请查看此DOM Processing with Perl文章。
那就是说。如果您的XML文件以可预测的方式生成,那么天真如下的东西可以起作用:
perl -pe 's#(<VALUE DECIMAL_VALUE=")([0-9.]+)(" UNIT_TYPE="percent"/>)#"$1" . ($2 + 0.4) . "$3"#e;'
答案 1 :(得分:3)
如果您完全确定XML的格式永远不会改变,那么属性的顺序是固定的,那么您确实可以获得正确数字的正则表达式...然后选择基于非解析器的解决方案。
我个人会使用XML :: Twig(也许是因为我写了它; - )。它将XML作为XML处理,同时仍然尊重文件的原始格式,并且在开始工作之前不会将其全部加载到内存中。
以下未经测试的代码:
#!/usr/bin/perl
use strict;
use warnings;
use XML::Twig;
XML::Twig->new( # call the sub for each VALUE element with a DECIMAL_VALUE attribute
twig_roots => { 'VALUE[@DECIMAL_VALUE]' => \&upd_decimal },
# print anything else as is
twig_print_outside_roots => 1,
)
->parsefile_inplace( 'foo.xml');
sub upd_decimal
{ my( $twig, $value)= @_; # twig is the XML::Twig object, $value the element
my $decimal_value= $value->att( 'DECIMAL_VALUE');
$decimal_value += 0.4;
$value->set_att( DECIMAL_VALUE => $decimal_value);
$value->print;
}
答案 2 :(得分:2)
这将输入stdin,输出到stdout:
while(<>){
if( $_ =~ /^(.*DECIMAL_VALUE=\")(.*)(\".*)$/ ){
$newVal = $2 + 0.04;
print "$1$newVal$3\n";
}else{
print $_;
}
}
答案 3 :(得分:0)
类似于以下内容将起作用。如果有额外的间距,可能需要调整,但这留给读者练习。
function update_after(in_string, locate_string, delta) {
local_pos = index(in_string,locate_string);
leadin = substr(in_string,0,local_pos-1);
leadout = substr(in_string,local_pos+length(locate_string));
new_value = leadout+delta;
quote_pos = index(leadout,"\"");
leadout = substr(leadout, quote_pos + 1);
return leadin locate_string new_value"\"" leadout;
}
/^ *\<VALUE/{
print update_after($0, "DECIMAL_VALUE=\"",0.4);
}
答案 4 :(得分:0)
这里是gawk
awk '/DECIMAL_VALUE/{
for(i=1;i<=NF;i++){
if( $i~/DECIMAL_VALUE/){
gsub(/DECIMAL_VALUE=|\042/,"",$i)
$i="DECIMAL_VALUE=\042"$i+0.4"\042"
}
}
}1' file