2013-11-22 194 views
1

我有一個由我的腳本附加的sitemap.xml文件(該腳本從我的動態站點製作靜態頁面並添加靜態頁面網址到網站地圖。)Perl - 如何刪除文件中匹配項的匹配行和「x」行

但是,有一種情況下,當$ SomeID頁面不再需要時,需要腳本刪除(5)行。

這裏是我想刪除時$ SomeID(12345例如)匹配Sitemap的一個部分的示例:

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

上面是我過去因各種原因使用的模塊的一個例子。

不需要在下面運行,但只需從另一個腳本粘貼。

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行,而無需創建臨時文件/使用兩個文件?

我在這裏看了一些類似的帖子,但是,沒有什麼能夠指出我的問題或者說明了我的理解。

我幾乎是一個noob,但耐心。 (原諒我上面的基本編碼技巧?) 我放棄了,所以我就是!

謝謝...

(我可以使用的模塊,比如領帶::如果需要的文件)

+0

這看起來像XML。難道你不能用一些標準模塊來解析它到通常的哈希結構數組,而不是正則表達式嗎? –

回答

1

那麼,最簡​​單的是,如果你在無論何時你發現邪惡的標識數組存儲$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回你的文件。

編輯:我忘記了如何接合完成後indides向下移動。上面的編輯應該處理,但不太好看。當然,我們可以嘗試按相反的順序遍歷數組,以超過索引shiftig問題。

+0

看起來很有希望,我現在試試。 – OldDogLearningNewPerlTricks

+0

JFYI,在第一次「拼接」之後,所有的下一行將會下移到新的索引。 –

+0

哇,拼接!但是,由於某種原因,我不得不改爲-2。 – OldDogLearningNewPerlTricks

1

這會將標籤內的所有數據保存在臨時變量中。當遇到另一個時,它會檢查temp變量是否包含someID。如果沒有,那麼它會推動@SiteMap數組中的行。最後,您只需要將@SiteMap的內容打印到新文件中。這並不完全符合您的要求,但使用開放標籤更有意義,而不是計數行。

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); 
+0

我可能會很累。但這似乎永遠不會推動任何東西給我。如果'$ line'與匹配,它只會被推送,但只有'$ line'匹配'$ SomeID'時纔會推送...我想它實際上是'$ tmprow',它不需要匹配'$ SomeID'來推送發生。 – DeVadder

+0

嗯,是的,我的錯誤,我編輯了代碼 – foibs

1

這真是非常混亂,很難將XML作爲字符串。起初看起來似乎比一些模塊更容易,但一旦你經過了學習曲線,解析器/寫入器的方法在每個級別上都會更好。

這是一種方法,可以提供更大的靈活性,並保證您最終獲得有效的XML。 Docs:XML::LibXMLXML::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> 
+1

+1使用適當的工具的工作。 –