5

我有一个带有以下行的 XML 文件:

            <VALUE DECIMAL_VALUE="0.2725" UNIT_TYPE="percent"/>

我想将此值增加 0.04 并保持 XML 的格式不变。我知道使用 Perl 或 awk 脚本可以做到这一点,但我很难用表达式来隔离数字。

4

5 回答 5

4

如果您在使用 xsltproc 命令的机器上,我建议您为此使用 XSLT。

对于 Perl 解决方案,我会选择使用 DOM。查看这篇使用 Perl 处理 DOM 的文章。

那就是说。如果您的 XML 文件是以可预测的方式生成的,那么像下面这样天真的事情可能会起作用:

perl -pe 's#(<VALUE DECIMAL_VALUE=")([0-9.]+)(" UNIT_TYPE="percent"/>)#"$1" . ($2 + 0.4) . "$3"#e;'
于 2009-01-15T20:39:37.553 回答
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;
  }
于 2009-01-15T21:51:23.963 回答
2

这在标准输入上输入,输出到标准输出:

while(<>){
 if( $_ =~ /^(.*DECIMAL_VALUE=\")(.*)(\".*)$/ ){
  $newVal = $2 + 0.04;
  print "$1$newVal$3\n";
 }else{
  print $_;
 }
}
于 2009-01-15T20:50:46.970 回答
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);
}
于 2009-01-15T20:38:02.440 回答
0

这是傻瓜

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
于 2009-11-24T23:41:52.773 回答