使用PERL删除第一行XML文件只有IF包含“XYZ”

时间:2012-11-24 19:07:25

标签: xml perl

我正在使用wget下载XML文件,但有时文件在第一行中有文本需要删除。

目前第一行有“131”,最后一行有“0”。

如果包含此信息,我需要一种删除这些行的方法。我不能做一个perl查找和替换,如果它不在那里,但正确的第一行包含“131”。

这有意义吗?

有什么想法吗?

由于

示例,有时是这样的:

131
<element>
<example>content</example>
<example>content</example>
<example>content</example>
<example>content</example>
</element>
0

有时候这样(正确)

<element>
<example>content</example>
<example>content</example>
<example>content</example>
<example>content</example>
</element>

3 个答案:

答案 0 :(得分:1)

我认为这可能会让你到达目的地。

假设你刚刚为sample.xml做了一个wget,那么:

perl -pi -e '$/ = undef; s{(?: \A [^<]* | [^>]* \z )}{}xmsg;' sample.xml

剥离任何非&lt;从文件的开头和任何不是&gt;从文件的末尾开始。

答案 1 :(得分:1)

这是sed的工作!你不会更快或更简单:

如果你确定这两个值,你可以简单地说:

sed -e  '1{/^131$/d};${/^0$/d}' -i mybrokenfile

但是使用以下命令,sed同时删除任何包含数字的第一行和/或最后一行:

sed -e '1{/^[0-9]\+$/d};${/^[0-9]\+$/d}'

这可以通过文件作为参数和备份文件自动生成来运行:

sed -e '1{/^[0-9]\+$/d};${/^[0-9]\+$/d}' -i.bak files*

说明:

  • 有两部分,1$ 地址:第一行为1,最后一行为$
  • 以下区块提供了另一种形式的逐个条件:/^[0-9]\+$/表示*行以09之间的一个或多个字符开头,并在紧接着之后结束。
  • 在此匹配行(第一行或最后一行)上,删除行的执行命令为d

这可以写成:

sed -e '1{
            /^[0-9]\+$/d
        }
        ${
            /^[0-9]\+$/d
        }' -i.bak files*

修改

因为我讨厌写不止一次......大概是什么;

有一种方法可以做一些棘手的事情,但只能在第一行和最后一行。

首先,同样的样本可以写成:

sed -e '1ba;$ba;bb;:a;/^[0-9]\+$/d;:b;' -i.bak files*

因此 1 字节更短!但尤其是操作只写一次:

说明:

  • :a:b是分支(跳转)到
  • 的标签
  • babb分别是:a:b的分支机构。
  • 1$是前面描述的地址
  • /.../d也是先前描述的,意思是删除与正则表达式相匹配的行

可写:

sed -e '
    1ba;
    $ba;
    bb;
   :a;
    /^[0-9]\+$/d;
   :b;
  ' -i.bak files*

使用s/../../代替d的应用示例: 仅在第1行或最后一行出现时修改版本信息:

 sed -e '1ba;$ba;bb;:a;s/\(Id: .*,v\).*\(Exp\)/\1'"$(
             date +" $VER %F %T $USER ")"'\2/;b;' -i files*

答案 2 :(得分:0)

根据评论,您希望使用wget --save-headers并使用正确的HTTP响应解析器。这其实很简单:

use HTTP::Response qw( );
my $response = HTTP::Response->parse($raw_response);
my $body = $response->decoded_content( charset => 'none' );  

鉴于响应包括$raw_response标题,上述代码将返回$body中传输的XML(或其他)文档。


原始回复:

这是一个HTTP分块响应。

if ($file =~ /^[0-9]+\r?\n/) {
   my $chunked = substr($file, 0, length($file), '');
   for (;;) {
      $chunked =~ s/^([0-9]+)\r?\n//
         or die;

      my $chunk_len = $1
         or last;

      length($file) >= $chunk_len
         or die;

      $file .= substr($chunked, 0, $chunk_len, '');
   }
}