【问题标题】:Using regex to parse a delimited array in bash使用正则表达式解析 bash 中的分隔数组
【发布时间】:2014-11-22 14:08:41
【问题描述】:

我有一个包含以下行的文件:

<polyline id="graph" points="0,287 100,470 200,509 300,459 400,471"/>

我需要提取以下值:

287 470 509 459 471

我目前正在使用此代码:

grep -oP '(?<=points=").*(?="/>)' "file.svg" | grep -oP '(?<=,)[[:digit:]]*'

我想用一个grep 来做,我尝试使用(?:),但没有成功。有什么建议吗?

【问题讨论】:

    标签: regex bash svg grep pcre


    【解决方案1】:

    一个 sed 解决方案可以像

    $ sed -r '/points=/ s/[^,]+,?([0-9]*)/\1 /g' input
    287 470 509 459 471 
    

    为了更好的处理

    $ sed -r '/points=/ s/.*points=("[^"]+").*/\1/g; s/[^,]+,?([0-9]*)/\1 /g' input
    287 470 509 459 471 
    

    【讨论】:

    • 嗯,如果行是这样的:<polyline foo="1,2,3,4" id="graph" points="0,287 100,470 200,509 300,459 400,471"/> 那么上面的 sed 产生:2 ,4 287 470 509 459 471
    • @anubhava 我也添加了包括在内。希望不会留下更多的漏洞;)
    【解决方案2】:

    如果你只是像这样解析一行,你可能会使用XML::Simple,像这样:

    perl -MXML::Simple -lwe'$x = XMLin(<>); print $x->{points};' file.svg
    

    用你的线,这给了我以下输出:

    0,287 100,470 200,509 300,459 400,471
    

    从该行解析的$x 中的整个结构在使用Data::Dumper 打印时如下所示:

    $VAR1 = {
              'points' => '0,287 100,470 200,509 300,459 400,471',
              'id' => 'graph'
            };
    

    请注意,如果输入比您在问题中指出的更复杂,您可能需要对其进行预处理。

    【讨论】:

    • 我忘了说那个平台上没有perl。我标记它是因为 -P 开关...
    【解决方案3】:

    它是 XML,所以解析为 XML。

    use XML::Twig;
    my $twig = XML::Twig -> new -> parse ( '<polyline id="graph" points="0,287 100,470 200,509 300,459 400,471"/>' );
    print $twig ->  root -> {'att'} -> {'points'};
    

    虽然 - 如果你想从 svg 文件中解析出来,你可能需要一些稍微不同的东西 - 但你可以使用$twig -&gt; parsefile

    简化为一条线:

    perl -MXML::Twig -e 'print XML::Twig -> new -> parsefile ("test.xml" ) -> root -> first_child("polyline") -> {"att"}{"points"};'  
    

    【讨论】:

      【解决方案4】:

      你可以使用 gnu-awk:

      awk -v RS='points="[^"]+"' 'RT{s=RT; gsub(/[^[:digit:], ]|[[:digit:]]+,/, "", s); 
         print s}' file
      287 470 509 459 471
      

      【讨论】:

        【解决方案5】:

        这个awk 应该这样做:

        awk -F\" '/points/ {gsub(/[0-9]+,/,"",$4);print $4}' file
        287 470 509 459 471
        

        如果线上的位置确实发生了变化,请执行以下操作:

        awk -F"points=" 'NF==2{gsub(/[0-9]+,|[^0-9 ]/,"",$2);print $2}' file
        287 470 509 459 471
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2014-05-08
          • 2016-12-03
          • 2021-11-27
          • 1970-01-01
          相关资源
          最近更新 更多