2012-07-29 59 views
6

我用正則表達式寫了一個小Perl腳本來獲取網站的HTML組件。使用一對Perl正則表達式匹配的無限循環

我知道它不是做這種工作的好方法,但我試圖測試我的正則表達式技巧。

當在while循環中運行兩個正則表達式模式中的任何一個時,它將完美運行並顯示正確的輸出。但是,當我嘗試在while循環中檢查兩個模式時,第二個模式每次匹配並且循環無限運行。

我的腳本:

#!/usr/bin/perl -w 
use strict; 

while (<STDIN>) { 

    while ((m/<span class=\"itempp\">([^<]+)+?<\/span>/g) || 
      (m/<font size=\"-1\">([^<]+)+?<\/font>/g)) { 
     print "$1\n"; 
    } 
} 

我有樣品輸入測試上面的腳本:

<a href="http://linkTest">Link title</a> 
<span class="itempp">$150</span> 
<font size="-1"> (Location)</font> 

所需的輸出:

$150 
(Location) 

謝謝!任何幫助將不勝感激!

+0

如果您正在處理多行文件,您將必須採用不同的方法。正如你在處理STDIN時明智地處理你的內心,同時仍然無用。使用HTML解析器是最不容易出錯的解決方案。你也可以嘗試用觸發器操作符匹配塊.. ..# – 2012-07-29 08:46:29

+0

@ mugenkenichi:廢話。外部'while'遍歷文件的行,內部遍歷行中模式的出現次數。爲什麼內部'while'無用? – Borodin 2012-07-29 08:51:53

+0

如果您正在處理多條線..我的意思是如果起始標籤與結束標籤位於不同的線上。無論如何,所有這些情況都可以通過專門的解析器處理得更好。 – 2012-07-29 08:54:13

回答

9

每當全局正則表達式匹配失敗時,它將重置下一個全局正則表達式將開始搜索的位置。所以,當你的兩個模式中的第一個模式失敗時,它會迫使第二個模塊再次從字符串的開頭看。

此行爲可以通過添加/c修飾符來禁用,如果正則表達式匹配失敗,修改器將保持該位置不變。

此外,您可以通過刪除轉義字符提高你的模式("不需要逃逸,/不需要進行轉義,如果你選擇一個不同的分隔符)和捕獲後的多餘+?

另外use warnings在命令行上比-w好得多。

這是您的代碼的工作版本。

use strict; 
use warnings; 

while (<STDIN>) { 

    while(m|<span class="itempp">([^<]+)</span>|gc 
      or m|<font size="-1">([^<]+)</font>|gc) { 
     print "$1\n"; 
    } 
} 
+2

+1實際解釋了OP代碼失敗的原因。 – 2012-07-29 10:51:13

+0

太棒了!我對perl不太滿意。我正在努力學習,因爲它很容易處理所有事情。感謝您清楚簡潔地解釋答案 – javaCity 2012-07-29 18:41:19

+0

在這個筆記上,我總是試圖學習正則表達式,但即使我知道'''做什麼和所有的基本東西,我不知道如何正確實現這些。任何提示呢?謝謝! – javaCity 2012-07-29 18:44:14

-3

在匹配後或匹配期間,您沒有更改$_,所以它始終會匹配並運行到無限循環。

要修復它,你可以在print之後加$_=$';,在剩下的字符串中再次運行匹配。

+0

謝謝!爲什麼這麼多downvotes呢? – javaCity 2012-07-29 08:17:14

+2

因爲分配給'$ _'是個好主意。特別是如果它不是必要的。除非你確切地知道你在做什麼以及你爲什麼需要它,否則應該避免這種骯髒的伎倆。 – 2012-07-29 08:19:46

+0

謝謝你澄清。 – javaCity 2012-07-29 08:29:24

3
while (<DATA>) { 
    if (m{<(?:span class="itempp"|font size="-1")>\s*([^<]+)}i) { 
     print "$1\n"; 
    } 
} 

__DATA__ 
<a href="http://linkTest">Link title</a> 
<span class="itempp">$150</span> 
<font size="-1"> (Location)</font> 
+0

我很抱歉,我不得不改變'正確的答案',因爲@Borodin提供了一個很好解釋的問題解答。不過謝謝你的努力。 – javaCity 2012-07-29 18:42:36