我有一個包含多個來自 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:3' | sed 's#&.*;##g'
Text3
這是第一個問題。第二個是所謂的「貪婪」匹配的概念:sed
將看到第一個&
,然後嘗試匹配它可以匹配的最大字串。如果單行上有多個 HTML 實體,這將是一個問題,因為:
$ echo 'Text:3 and some more text å and end' | sed 's#&.*;##g'
Text and end
如果您想在上下文中查看修復sed
,您可以透過匹配任意數量的“來查找實體的結束字符不是 ;
" 在結束之前;
執行以下操作:
$ echo 'Text:3 and some more text å and end' | sed 's#&[^;]*;##g'
Text3 and some more text and end
&
您仍然會遇到文本中與號 ( ) 的合法使用問題(嗯,&
這是真正的“合法”使用,但現實世界並不總是像理想的那樣可解析)並且匹配太多,但這解釋了為什麼sed
會有這樣的行為。
答案2
用實際字元替換代碼不是更好嗎?
echo 'Text1™
[Text®2]
Text:3' | perl -C -pe 's/&#([^;]*)/chr$1/eg'
輸出:
Text1™;
[;Text®;2];
Text:;3