2010-08-01 22 views
2

我的目標是將尾隨的所有實例 - 替換爲標籤括號內的尾隨+。讓我們假設要被替換的行看起來是這樣的:Perl:標籤分隔字符串中的全局替換

<h> aa- aa- </h> <h> ba- ba- </h> 

,應該事後看起來像

<h> aa+ aa+ </h> <h> ba+ ba+ </h> 

首先我嘗試這樣表達:

s/<h>(.*?)-(.*?)<\/h>/<h>$1+$2<\/h>/g; 

其產生這樣的輸出:

<h> aa+ aa- </h> <h> ba+ ba- </h> 

g op這會導致每行有多個替換,但僅限於每個標記支架的第一個實例(並且只有在兩個圓括號都包含問號時)。

爲了縮小這個問題,我然後試圖實現不考慮標籤的替換。表達

s/(.*?)-(.*?)/$1+$2/g; 

確實導致所需結果

<h> aa+ aa+ </h> <h> ba+ ba+ </h> 

這將替換標記括號的外面,以及,當然。

那麼,我的第一個表達式有什麼問題,我如何實現我在標籤括號內完全替換的目標?

+0

如果之前一切以字符集的任何限制的'-'你可以利用它。 – adamse 2010-08-01 11:36:18

+1

您應該使用完整的解析器,而正則表達式不是。 – Ether 2010-08-01 17:08:54

回答

0

以下是一種方法:將字符串拆分爲帶標籤位和未帶標籤位,並僅對帶標籤位進行置換。

$_ = join("", map { if(/^<h>/) { # if it's a tagged bit... 
         s/-($|\s|<)/+$1/g; # replace all trailing '-'s 
        } 
        $_} 
        split m!(<h>.*?</h>)!) # split into tagged and non-tagged bits 
1

既然你解析正則表達式的XML(而不是在一般情況下是個好主意),我想你是願意讓你輸入一些假設。如果是這樣,下面的替代可能會足夠好。

它用加號替換減號,前提條件是減號是:(a)在單詞邊界處,(b)後面跟隨一些可選的非左角括號文本,然後是關閉標記。如果我們可以假設有效的文檔,則無需擔心開始標記。第二個條件是通過預讀斷言強制執行的,以便正則表達式不會消耗字符串,從而可以替換所有這些減號。

s/ \b- (?= [^<]* <\/h>) /+/xg; 

另一種選擇是運行您的正則表達式,直到它無法替換任何東西。在一個標量上下文全局替換返回替換所做的數量,這可以作爲你的測試時停止加工線:

my $n = 1; 
$n = s/YOUR_REGEX/YOUR_REPLACE/g while $n;