如何阻止此Perl命令一遍又一遍地打印XML声明?

时间:2015-08-27 16:22:37

标签: linux perl

我在Red Hat Linux中运行以下命令:

perl -ne '
    print "<?xml version=\"1.0\" encoding=\"utf-8\"?>";
    while(/(<PRINTKIT FORM_ID=\"PP_WELCOMEKIT\">.*?<\/PRINTKIT>)/g){
        print "<sf><XDF>$1</XDF></sf>"
    };
' $1 > $2.$TS2.postscrub

$2是文件名,$TS2只是一个日期。

目前它打印出100行

<?xml version=\"1.0\" encoding=\"utf-8\"?>

当我真的不想要打印任何内容时。

有人可以更改上面的代码来执行它正在执行的所有操作,但不再打印<?xml version=\"1.0\" encoding=\"utf-8\"?>了吗?我已经尝试过删除带有该行的print语句,如下所示:

perl -ne '
    while(/(<PRINTKIT FORM_ID=\"PP_WELCOMEKIT\">.*?<\/PRINTKIT>)/g){ 
        print "<sf><XDF>$1</XDF></sf>"
    };
' $1 > $2.$TS2.postscrub

这样做会使它输出一个0字节的文件,所以我知道它不起作用。

4 个答案:

答案 0 :(得分:7)

真的 - 请不要使用正则表达式来操纵XML。它是非常令人讨厌的,正如你所发现的那样 - 容易被莫名其妙地打破。

尝试这样的事情(我猜测了你的样本数据)。

#!/usr/bin/env perl

use strict;
use warnings;

use XML::Twig;

sub replace_printkit {
    my ( $twig, $pk ) = @_;
    my $sf = $twig->root->insert_new_elt('sf');
    $sf->insert_new_elt( 'XDF', $pk->trimmed_text );
    $pk->delete;
}

my $twig = XML::Twig->new(
    'pretty_print'  => 'indented',
    'twig_handlers' => { 'PRINTKIT' => \&replace_printkit }
);

$twig->parse( \*DATA );
$twig->set_xml_version('1.0');
$twig->set_encoding('utf-8');
$twig->print;


__DATA__
<xml>
  <PRINTKIT FORM_ID="PP_WELCOMEKIT">some_stuff_here</PRINTKIT>
</xml>

打印:

<?xml version="1.0" encoding="utf-8"?>
<xml>
  <sf>
    <XDF>some_stuff_here</XDF>
  </sf>
</xml>

您可能需要稍微修改输入数据。

编辑:

  

当您使用$ twig-&gt; print时,我可以将其放入文件中吗?如果是这样,命令是什么?

open ( my $output_fh, '>', "new_file.xml" ) or die $!;
print {$output_fh} $twig -> sprint;
close ( $output_fh );

答案 1 :(得分:4)

除了使用正则表达式XML的可取性之外,这个问题的简单答案是:&#34;如何阻止这个Perl命令一遍又一遍地打印XML声明?&#34;是将XML声明包装在BEGIN块中。

BEGIN { print "<?xml version=\"1.0\" encoding=\"utf-8\"?>" }

perlrun描述了-n切换效果:

  

导致Perl在程序周围采用以下循环,这使得它迭代文件名参数,有点像sed -n或awk

    LINE:
    while (<>) {
    ...     # your program goes here
    }

因此,无论你在-n程序的主体中放置什么,都会为每行输入运行,从而重复打印XML标记。如果用BEGIN包装它,它就不会那么做。

但是,-n行为所以为Perl建立了,并且重复XML标记对于XML来说是非标准的,所以它很适合任何人#39解决方案的想法。我几乎怀疑那些不知道它在做什么的人,删除了BEGIN块,只是因为它是一个明显的候选者。

答案 2 :(得分:4)

perl -ne'
    BEGIN { print "<?xml version=\"1.0\" encoding=\"utf-8\"?>"; }
    while(/(<PRINTKIT FORM_ID=\"PP_WELCOMEKIT\">.*?<\/PRINTKIT>)/g){
        print "<sf><XDF>$1</XDF></sf>"
    }
' $1 > $2.$TS2.postscrub

perl -ne'
    print "<?xml version=\"1.0\" encoding=\"utf-8\"?>" if $. == 1;
    while(/(<PRINTKIT FORM_ID=\"PP_WELCOMEKIT\">.*?<\/PRINTKIT>)/g){
        print "<sf><XDF>$1</XDF></sf>"
    }
' $1 > $2.$TS2.postscrub

perl -e'
    print "<?xml version=\"1.0\" encoding=\"utf-8\"?>";
    while (<>) {
        while(/(<PRINTKIT FORM_ID=\"PP_WELCOMEKIT\">.*?<\/PRINTKIT>)/g){
            print "<sf><XDF>$1</XDF></sf>"
        }
    }
' $1 > $2.$TS2.postscrub

答案 3 :(得分:0)

您必须保留参数-n。它为您的代码添加了一个while循环。你只需要一个有效的while循环,将其更改为读取所有行(while (<>)),你可以将你的条件放在print语句之后,如下所示:

perl -e '
    print "<?xml version=\"1.0\" encoding=\"utf-8\"?>";
    while(<>) {
        print "<sf><XDF>$1</XDF></sf>" if(/(<PRINTKIT FORM_ID=\"PP_WELCOMEKIT\">.*?<\/PRINTKIT>)/g);
    };' $1 > $2.$TS2.postscrub