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 次或更多次。前一个字符是&,因此这将匹配例如&&&;;&在之前写了 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

相关内容