我有一个由我的脚本附加的sitemap.xml文件(该脚本从我的动态网站创建静态页面,并将静态页面网址添加到站点地图。)
但是,有一种情况我需要脚本在不再需要$ SomeID页面时删除(5)行。
以下是我想在$ SomeID(例如12345)匹配时删除的站点地图部分的示例:
<url>
<loc>http://mydomain.com/directory/some-page-name-34-098765.htm</loc>
<changefreq>daily</changefreq>
<priority>0.5</priority>
</url>
#I want to delete from here
<url>
<loc>http://mydomain.com/directory/some-page-name-340-12345.htm</loc>
<changefreq>daily</changefreq>
<priority>0.5</priority>
</url>
##to here (when 12345 is matched (done below))
<url>
<loc>http://mydomain.com/directory/some-page-name-445-45673.htm</loc>
<changefreq>daily</changefreq>
<priority>0.5</priority>
</url>
现在,我可以找到该行及其编号:
#!/usr/bin/perl -w
use CGI;
use CGI::Carp qw(fatalsToBrowser warningsToBrowser);
print CGI::header();
use strict;
use warnings;
use LWP::Simple qw(!head);
use Fcntl; #needed for the verbose file handler calls like O_CREAT
use File::Slurp;
use File::Basename;
use DBI;
use Tie::File;
ABOVE是我过去因各种原因使用的模块示例。
不需要在下面运行,但只是从另一个脚本粘贴。
my $SiteMapFile = 'sitemap.xml';
my $fh;
my $SomeID='12345';
my $cnt = '1';
my @SiteMap;
open($fh, "<", $SiteMapFile ) || die "Can't open $SiteMapFile: $!";
my @maplines = <$fh>;
foreach(@maplines){
if ($_ =~ $SomeID){
print qq~Match in sitemap Sitemap Line $_<br />~;
push(@SiteMap, $_);
print qq~Found match at line number $cnt<br />;
}
$cnt++;
}
close $fh;
我将匹配线推入阵列,我想下一步。
有没有办法可以通过'行号删除一行?
那么,我可以删除该行,它之前的行和它之后的3行没有创建临时文件/使用两个文件?
我在这里查看了一些类似的帖子,但没有任何问题可以解决我的问题,或者将其解释为我的理解点。
我几乎是个菜鸟,但耐心等待。 (请原谅我上面的基本编码技巧?) 我放弃了,我在这里!
...谢谢
(如果需要,我可以使用像Tie :: File这样的模块)
答案 0 :(得分:1)
嗯,最简单的是,如果您在找到邪恶的Id时将$cnt
存储在数组中,请说该数组名为@badLines
。这样你就可以获得需要删除它们的所有行号。然后你需要一个循环:
my $index=0;
foreach(@badLines)
{
splice (@maplines, $_-1-($index*5), 5); # Remove 5 lines starting one before the offending one.
$index++;
}
http://perldoc.perl.org/functions/splice.html
然后您只需将@maplines
打印回文件即可。
编辑:我忘了每当拼接完成时,indize如何向下移动。上面的编辑应该处理,但看起来不太好看。当然可以尝试以相反的顺序迭代数组以超越索引shiftig问题。
答案 1 :(得分:1)
这会将标记内的所有数据保存在临时变量中。当遇到另一个时,它会检查temp变量是否包含someID。如果没有,则它会推送@SiteMap数组中的行。最后,您只需要将@SiteMap的内容打印到新文件中。它并不完全是你提出的问题,但使用open标签更有意义,而不是计算行数。
my $SiteMapFile = 'sitemap.xml';
my $fh;
my $SomeID='12345';
my $cnt = 1;
my @SiteMap;
open($fh, "<", $SiteMapFile ) || die "Can't open $SiteMapFile: $!";
my @maplines = <$fh>;
my $tmprow;
foreach my $line(@maplines){
if ($line =~ /<url>/){
push @SiteMap, $tmprow if ($tmprow !~ /$SomeID/);
$tmprow = $line;
} else {
$tmprow .= $line."\n";
}
$cnt++;
}
close $fh;
#dont forget to check the last element
push @SiteMap, $tmprow if ($tmprow !~ /$SomeID/);
print join("\n", @SiteMap);
答案 2 :(得分:1)
将XML固定为字符串非常麻烦和困难。它最初看起来比某些模块更容易,但是一旦你超越了学习曲线,解析器/编写器方法在每个级别上都会更好。
这种方法可以提供更大的灵活性,并保证您最终获得有效的XML。文档:XML::LibXML,XML::LibXML::XPathContext。
use XML::LibXML;
use XML::LibXML::XPathContext;
my $doc = XML::LibXML->new->parse_fh(\*DATA);
my $xc = XML::LibXML::XPathContext->new($doc);
$xc->registerNs( sitemap => $doc->documentElement->namespaceURI );
for my $loc ( $xc->findnodes('//sitemap:loc') )
{
# Up to you to make the match/check sane and robust.
$loc->parentNode->unbindNode
if $loc->textContent =~ /\b 12345 \b/x;
}
print $doc->toString(1);
__DATA__
<?xml version="1.0" encoding="UTF-8"?>
<urlset xsi:schemaLocation="http://www.sitemaps.org/schemas/sitemap/0.9 http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
-- snipped your URLs for space --
</urlset>