sed 正規表示式刪除特殊字符

sed 正規表示式刪除特殊字符

我有一個包含多個來自 HTML 格式文字的字串的文件,因此它們有一些在控制台介面中看起來不太好的 HTML 序列。這是一個例子:

Text1™
[Text®2]
Text:3

我正在嘗試的是刪除 & 和 ; 之間的所有內容。因此文本再次可讀,如下所示:

Text1
Text2
Text3

我實際上正在嘗試使用 sed 刪除多餘的字元:

sed 's#&*;##g' <file>

問題是它只刪除了 ;來自文字字串。

那麼問題是,應該如何對正規表示式進行編碼才能刪除額外的鏈:&#[1-9]+;

答案1

你的正規表示式

sed 's#&*;##g' <file>

不做你認為它會做的事。該*字元是一個乘數,表示前面的字元重複 0 次或多次。前一個字元是&,所以這會匹配例如&&&;and ;&之前寫了 0 次;!這是您的測試案例中匹配的內容),但在這種情況下不是您想要的。

您需要指定“任何乘數之前的字元”,由單點 表示.

$ echo 'Text&#58;3' | sed 's#&.*;##g'
Text3

這是第一個問題。第二個是所謂的「貪婪」匹配的概念:sed將看到第一個&,然後嘗試匹配它可以匹配的最大字串。如果單行上有多個 HTML 實體,這將是一個問題,因為:

$ echo 'Text&#58;3 and some more text &aring; and end' | sed 's#&.*;##g'
Text and end

如果您想在上下文中查看修復sed,您可以透過匹配任意數量的“來查找實體的結束字符不是 ;" 在結束之前;執行以下操作:

$ echo 'Text&#58;3 and some more text &aring; and end' | sed 's#&[^;]*;##g'
Text3 and some more text  and end

&您仍然會遇到文本中與號 ( ) 的合法使用問題(嗯,&amp;這是真正的“合法”使用,但現實世界並不總是像理想的那樣可解析)並且匹配太多,但這解釋了為什麼sed會有這樣的行為。

答案2

用實際字元替換代碼不是更好嗎?

echo 'Text1&#8482;
&#91;Text&#174;2&#93;
Text&#58;3' | perl -C -pe 's/&#([^;]*)/chr$1/eg'

輸出:

Text1™;
[;Text®;2];
Text:;3

相關內容