需要在Linux环境中使用Perl脚本修改多个XML文件

时间:2013-05-08 16:23:21

标签: xml linux perl

我在目录中有几个名为TC_Circle1TC_Circle2,`TC_Point1等的XML文件,我想使用脚本来更新每个文件中的开始和停止日期。开始和停止日期在内部,每个文件中都有标签。

我有一个脚本在我们使用Sun机器时起作用,但它不适用于新的HP Linux机器。它不显示任何错误,也不会更改日期。我需要帮助它在Linux中工作。脚本:

#!/usr/local/bin/perl
$numArgs = @ARGV;
if ($numArgs != 2) 
{
print "Usage: replace_default_date.pl DEFAULT_START_DATE DEFAULT_STOP_DATE\n";
}

@filenames = `ls TC*`;
chomp(@filenames);
foreach $file (@filenames)
{
  open(REGFILE, "$file") || die "Cannot open |$file|";
  @lines = <REGFILE>; 
  close(REGFILE);

  open(WRITEFILE), ">$file") || die "Cannot open |$file|";

  foreach $line (@lines)
  {
    if ($line =~ /DEFAULT_START_DATE/)
    {
      $newline = "  " . $ARGV[0];
      print WRITEFILE "$newline\n";
    }
    elsif ($line =~ /DEFAULT_STOP_DATE/)
    {
      $newline = "  " . $ARGV[1];
      print WRITEFILE "$newline\n";
    }
    else 
    {
      print WRITEFILE "$line\n";
    }
  }
  close  (WRITEFILE);
}

以下是要修改的文件在开头看的方式:

<RequestSomething xmlns="http://something.com/accessservice">
   <period xmlns="">
     <start>2013-03-06T00:00:00</start>
     <stop>2013-03-07T00:00:00</stop>
   </period>
    ... The rest of the xml file...
 </RequestSomething>

提前致谢, 晶体

3 个答案:

答案 0 :(得分:1)

您的脚本存在一些问题。

1)由于额外的右括号,存在编译错误:

  

打开(WRITEFILE),“&gt; $ file”)||死“无法打开| $ file |”;

应该写为

  

打开(WRITEFILE,“&gt; $ file”)||死“无法打开| $ file |”;

2)你应该在

中使用反引号而不是单引号
@filenames = 'ls TC*';

否则@filenames将只包含字符串'ls TC *'而不是实际的文件名列表:

@filenames = `ls TC*`;

3)你确定perl解释器的路径是/usr/local/bin/perl吗? (从命令行尝试which perl以检查路径)。如果不是那么第一行应该改变。

4)该脚本永远不会对您向我们展示的XML数据起作用,因为它旨在替换包含字符串 DEFAULT_START_DATE DEFAULT_STOP_DATE 的行(日期提供为脚本的参数)。这些字符串不会出现在您向我们展示的数据中。

但是,如果XML文件是这样的话,该脚本将起作用:

<RequestSomething xmlns="http://something.com/accessservice">   
    <period xmlns="">
      <start>
          DEFAULT_START_DATE     
      </start>
      <stop>
          DEFAULT_STOP_DATE
      </stop>
    </period>
     ... The rest of the xml file...
 </RequestSomething>

我希望这可以帮助你让它工作,但无论如何我建议你重写脚本,因为它使用了一种非常不可靠和危险的方式来更改XML文件。

答案 1 :(得分:0)

由于您想要做的事情相对简单,因此您并不需要将其视为.xml。我会像你一样对待它,以免混淆。对于你的方式,似乎Tie :: File是一个很好的选择。例如:

的test.xml:

<RequestSomething xmlns="http://something.com/accessservice">
   <period xmlns="">
     <start>2013-03-06T00:00:00</start>
     <stop>2013-03-07T00:00:00</stop>
   </period>
    ... The rest of the xml file...
 </RequestSomething>

代码:

use Tie::File;
use strict;
use warnings;

my @ra=();
tie @ra, 'Tie::File', "test.xml" or die;
my $length=scalar(@ra);

for (my $i=0; $i < $length; $i++)
{
    if ($ra[$i] =~ /(\s*)<start>.*<\/start>/)
    {
        $ra[$i]="$1<start>$ARGV[0]<\/start>";
    }
    elsif ($ra[$i] =~ /(\s*)<stop>.*<\/stop>/)
    {
        $ra[$i]="$1<stop>$ARGV[1]<\/stop>";
    }
}

使用Tie :: File,您可以进入您的文件,并使用数组来访问/修改其内容。 (\s*)<stop>.*<\/stop>基本上执行以下操作:(\ s *)在$ 1之前提取所有空格。 <stop>.*<\/stop>在它们之间查找包含任何非换行符的停止标记。一旦我们知道我们在正确的行中,我们只需通过修改数组来改变该行,正如我所说的直接更改文件。我们把1美元放在那里以保留缩进。

这里是我执行perl test.pl 1am 2pm时的新test.xml:

<RequestSomething xmlns="http://something.com/accessservice">
   <period xmlns="">
     <start>1am</start>
     <stop>2pm</stop>
   </period>
    ... The rest of the xml file...
 </RequestSomething>

您可以添加选项以浏览所有必需的文件,只需确保在每个文件之后重置数组,即@ ra =();祝好运。希望这有帮助!

编辑:看看关于解开阵列的评论,你也应该这样做。

答案 2 :(得分:0)

为什么不使用XML解析器?你不能在那台机器上安装CPAN吗?

如果文件不大,您可以使用XML::Simple,否则使用XML::Twig - 如果您不习惯回调处理程序可能会很棘手。

我用XML::XPath向您展示了一个简单的方法。

use XML::XPath;
use DateTime;

my $xp = XML::XPath->new(filename => 'input.xml');

$xp->setNodeText('/RequestSomething/period/start', DateTime->now->strftime("%FT%T"));
$xp->setNodeText('/RequestSomething/period/stop', DateTime->now->add(days=>1)->strftime("%FT%T"));

open my $fh, '>', 'output.xml' or die "$!";
print $fh $xp->getNodeAsXML();
close $fh; 

我使用DateTime来设置当前日期,但您当然可以不使用它。