2012-06-09 79 views
4

我想要替換以下html文本的一部分(摘錄一個巨大的文件),更新舊的論壇格式(從一個非常糟糕的論壇移植工作2年前完成)到常規phpBB格式:sed正則表達式在第一場比賽停止

<blockquote id="quote"><font size="1" face="Verdana, Arial, Helvetica" id="quote">quote:<hr height="1" noshade id="quote"><i>written by User</i> 

這應該被過濾到:

[quote=User] 

我用下面的正則表達式在sed

s/<blockquote.*written by \(.*\)<\/i>/[quote=\1]/g 

這適用於給定示例,但在實際文件中,像這樣的幾個引號可以在一行中。在這種情況下,sed太貪婪,並且在[quote = ...]標籤中的第一個和最後一個匹配之間放置所有內容。我似乎無法使它在行中取代這種模式的每一個發生...(我不認爲有任何嵌套的引號,但這會使它更難)

+0

'sed' Perl的正則表達式:['ssed'(https://launchpad.net/ssed) –

回答

3

你需要一個版本的sed的(1)使用Perl兼容的正則表達式,這樣就可以做這樣的事情做一個最小的匹配,或一個具有負先行。

最簡單的方法是首先使用Perl。

如果您有一個現有的sed腳本,您可以在使用S2P(1)實用程序翻譯成Perl的。請注意,在Perl中,您確實想要在s///運算符的右側使用$1。在大多數情況下,\1的祖父,但一般而言,您想$1有:

s/<blockquote.*?written by (.*?)<\/i>/[quote=$1]/g; 

通知我已刪除從括號前面的反斜槓。使用Perl的另一個優點是,它採用了理智egrep的風格的正則表達式(如AWK),不醜的grep風格的人(如sed的)需要所有這些混亂(和不一致的)所有反斜槓在那個地方。

使用Perl的另一個優點是可以使用成對的可嵌套分隔符來避免醜陋的反斜槓。例如:

s{<blockquote.*?written by (.*?)</i>} 
{[quote=$1]}g; 

其他優勢包括Perl的相處很好很好用UTF-8(現在網絡的多數編碼格式),並且,你可以做多場比賽沒有極端痛苦sed的需要爲。例如:

$ perl -CSD -00 -pe 's{<blockquote.*?written by (.*?)</i>}{[quote=$1]}gs' file1.utf8 file2.utf8 ... 

-CSD使得治療標準輸入,標準輸出和文件爲UTF-8。 -00使其一次讀取整個文件,並且/s使點根據需要跨越換行邊界。

+0

太棒了!有趣的是,我首先從Perl開始,但由於它速度要快得多,所以我被引誘使用sed ......不知道它在這方面是如此有限。不知道是否-00是一個好主意,因爲它是一個500M文件(sql包含html,我在第一篇文章中是不完整的)。非常感謝!!! – Ewout

0

我不認爲sed支持非-greedy比賽。你雖然可以嘗試的Perl:

perl -pe 's/<blockquote.*?written by \(.*\)<\/i>/[quote=\1]/g' filename 
+1

好主意,但這樣做不太剛下班的路上佑都:你忘了切換使用* egrep *樣式的反斜槓越少,所以你沒有捕獲任何東西。看到我的答案。 – tchrist

+0

aaaaaah好的@tchrist –

0

這可能會爲你工作:

sed '/<blockquote.*written by .*<\/i>/!b;s/<blockquote/\n/g;s/\n[^\n]*written by \([^\n]*\)<\/i>/[quote=\1]/g;s/\n/\<blockquote/g' file 

說明:

  • 如果某行不包含模式,然後跳過它。 /<blockquote.*written by .*<\/i>/!b
  • 在整條線上將模式的前端更改爲全局換行符。 s/<blockquote/\n/g
  • 全局替換換行符,然後使用[^\n]*而不是.*替換其餘的格式。 s/\n[^\n]*written by \([^\n]*\)<\/i>/[quote=\1]/g
  • 恢復這些換行符不會更改爲原來的前方格局。 s/\n/\<blockquote/g
相關問題