2013-05-08 64 views
2

我在目录中有几个名为TC_Circle1TC_Circle2,`TC_Point1等的XML文件,我想用脚本更新每个文件中的开始和结束日期。开始日期和结束日期在每个文件内部和标签中。需要在Linux中使用Perl脚本修改几个XML文件env

我在使用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> 

感谢, 水晶

+0

你能告诉我们一个(简短的!)输入数据的例子吗? – mirod 2013-05-08 16:29:18

+1

非常危险。如果此程序在开始写入后死亡,则会丢失文件。它应该写入临时文件然后替换。 – stark 2013-05-08 16:34:51

+0

该脚本写得相当不错,并且不会将这些文件视为XML。它也不会在同一个文件上运行两次。你确定原文有单引号的“ls TC *”,而不是反引号,这将需要将字符串作为shell命令运行? – amon 2013-05-08 16:39:41

回答

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>"; 
    } 
} 

使用领带::文件,你可以进入你的文件,并使用数组访问/修改其内容。 (\s*)<stop>.*<\/stop>基本上做到以下几点:(\ s *)将所有空间提取到$ 1之前。 <stop>.*<\/stop>查找在它们之间具有任何一组非换行符的停止标签。一旦我们知道我们处于正确的位置,我们只需通过修改数组来更改该行,正如我所说的那样直接更改文件。我们在那里放置1美元来保存缩进。

这里的时候,我的perl执行凌晨1点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 =();祝你好运。希望这可以帮助!

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

+0

PS:不知道你对perl有多熟悉,但是如果你没有安装Tie :: File,这是行不通的。要安装它,只需进入cmd或终端并通过键入“cpan”(不包括引号)来打开cpan shell。打开cpan后键入:“install Tie :: File”并按回车。然后你的perl模块将自行安装。 – 2013-05-08 17:14:18

+1

我认为最好总是'解开@ array'。 – chrsblck 2013-05-08 17:30:19

+0

虽然OP从'cpan'安装东西,但现在是安装“XML”解析器的好时机。例如。 'XML :: LibXML'或['XML :: Parser'](http://search.cpan.org/~msergeant/XML-Parser-2.36/Parser.pm)。 – chrsblck 2013-05-08 17:33:05

1

脚本有几个问题。

1)是因为一个额外的右括号的编译错误:

开放(WRITEFILE), “> $文件”)||死“无法打开| $文件|”;

应当书面方式为

开放(WRITEFILE, “> $文件”)||死“无法打开| $文件|”;

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文件。

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设置当前日期,但你当然可以没有它。