【问题标题】:Parsing XML - Subtracting values from tags解析 XML - 从标签中减去值
【发布时间】:2013-02-08 22:46:15
【问题描述】:

我在一个非常大的文件中有以下 xml 结构:

<sit>619709.6044;144998.7059;-090372.58119</sit>
<vll>0;0;0</vll>
<cor>255;0;255</cor>

如何减去 sit 标记中的值?该标签由 ; 分隔的三个值组成,每个值都必须从特定数字中减去。

可以使用任何 unix 工具。 (awk、sed、bc 等)

因此,如果该特定数字对于第一个值是 1000,对于第二个值是 100,对于第三个值是 10,那么结果将是:

<sit>618709;144898;-090362</sit>
<vll>0;0;0</vll>
<cor>255;0;255</cor>

无需保留分数。

【问题讨论】:

    标签: linux xml-parsing sed awk bc


    【解决方案1】:

    这是使用awk 的一种方式。运行如下:

    awk -v a=1000 -v b=100 -v c=10 -F "[<;>]" -v OFS=";" -f ./script.awk file
    

    script.awk的内容:

    /^<sit>/ && /<\/sit>$/ {
        $0 = "<sit>" format($3, a) OFS format($4, b) OFS format($5, c) "</sit>"
    }1
    
    function format(field, var) {
        f = sub(/^-/, "", field)
        return (f == 1 ? "-" : "") sprintf("%06d", int(field-var))
    }
    

    结果:

    <sit>618709;144898;-090362</sit>
    <vll>0;0;0</vll>
    <cor>255;0;255</cor>
    

    您还没有完全清楚如何格式化您的输出。看起来您希望整数最多填充六个前导零,无论它们是正数还是负数。上面的脚本会做到这一点。如果那个零实际上是一个错字,那么这个单行就足够了:

    awk -v a=1000 -v b=100 -v c=10 -F "[<;>]" -v OFS=";" '/^<sit>/ && /<\/sit>$/ { $0 = "<sit>" sprintf("%06d",int($3-a)) OFS sprintf("%06d",int($4-b)) OFS sprintf("%06d",int($5-c)) "</sit>" }1' file
    

    结果:

    <sit>618709;144898;-90382</sit>
    <vll>0;0;0</vll>
    <cor>255;0;255</cor>
    

    【讨论】:

    • 正是我想要的...填充。对不起我虚弱的功夫英语。
    【解决方案2】:
    awk '
    BEGIN{ split("1000 100 10",dec); FS=OFS=";" }
    gsub(/<\/?sit>/,"") {
       for (i=1;i<=NF;i++)
          $i = int($i - dec[i])
       $0="<sit>" $0 "</sit>"
    }
    1' file
    <sit>618709;144898;-90382</sit>
    <vll>0;0;0</vll>
    <cor>255;0;255</cor>
    

    【讨论】:

      【解决方案3】:

      XML::Twig 解析器的帮助下使用perl 的一种方式:

      假设xmlfile有以下数据:

      <root>
              <sit>619709.6044;144998.7059;-090372.58119</sit>
              <vll>0;0;0</vll>
              <cor>255;0;255</cor>
      </root>
      

      还有script.pl的代码:

      #!/usr/bin/env perl
      
      use warnings;
      use strict;
      use XML::Twig;
      use POSIX qw<floor ceil>;
      
      my @substracts = qw<1000 100 10>;
      
      my $twig = XML::Twig->new(
          twig_handlers => {
              'sit' => sub { 
                  my @sit_values = map { $_ < 0 ? ceil $_ : floor $_  } split /;/, $_->text_only;
                  for my $i ( 0 .. $#substracts ) { 
                      $sit_values[ $i ] -= $substracts[ $i ];
                  }   
      
                  $_->set_text( join q|;|, @sit_values );
              }   
          },  
          pretty_print => 'indented',
      )->parsefile( shift )->print;
      

      像这样运行它:

      perl-5.14.2 script.pl xmlfile
      

      产生:

      <root>
        <sit>618709;144898;-90382</sit>
        <vll>0;0;0</vll>
        <cor>255;0;255</cor>
      </root>
      

      【讨论】:

        猜你喜欢
        • 2016-04-24
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-03-13
        • 2016-02-12
        • 1970-01-01
        • 1970-01-01
        • 2021-03-18
        相关资源
        最近更新 更多