2

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

当我们使用 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>

在此先感谢,水晶

4

3 回答 3

1

您的脚本有几个问题。

1)由于额外的右括号导致编译错误:

打开(WRITEFILE), ">$file") || die "无法打开 |$file|";

应该写成

打开(WRITEFILE, ">$file") || die "无法打开 |$file|";

2)你应该使用反引号而不是单引号

@filenames = 'ls TC*';

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

@filenames = `ls TC*`;

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

4) 该脚本将永远无法处理您向我们展示的 XML 数据,因为它旨在替换包含字符串DEFAULT_START_DATEDEFAULT_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 文件。

于 2013-05-08T17:57:46.360 回答
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设置当前日期,但您当然可以不使用它。

于 2013-05-08T21:04:24.147 回答
0

由于您想要做的事情相对简单,因此您实际上不需要将其视为 .xml。我会像你一样对待它,以免造成混乱。对于您的操作方式,似乎 Tie::File 是一个不错的选择。例如:

测试.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 放在那里以保留缩进。

这是我在凌晨 1 点 2 点执行 perl test.pl 时的新 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=(); 祝你好运。希望这可以帮助!

编辑:请参阅关于 untie array 的评论,您也应该这样做。

于 2013-05-08T16:59:57.430 回答