我使用以下perl正则表达式从输入中清除xml / html样式格式化标记。
$expr = qr{
<\s*a(?:\s*|\s+[^>]+)>
((?:
(?> (?:(?!(<\s*a(?:\s*|\s+[^>]+)>|<\/\s*a\s*>)).)+ )
|
(??{ $expr })
)*)
<\/\s*a\s*>
}x;
递归地应用它会删除嵌套的<a>...</a>
标记(如果<a>
生成超链接,这不会有意义)并且只保留括号内的文本:
my $tmp_text = "a<a> e </a>c<a href="test">g <a> d</a> d</a>f";
print $tmp_text."\n";
$tmp_text=~s/$expr/$1/g;
print $tmp_text."\n";
$tmp_text=~s/$expr/$1/g;
print $tmp_text."\n";
这将打印
a<a> e </a>c<a href="test">g <a> d</a> d</a>f
a e cg <a> d</a> df
a e cg d df
现在,我想对所有其他格式标记执行相同操作,例如<b>..</b>
等。我肯定会列出所有支持的代码,在a
中将b
替换为$expr
等,然后对每个代码重复替换。
但是,我想知道是否有更高效/更紧凑的方式修改$expr
,以便它会对name
中的<name something>...</name>
进行平衡匹配。
请注意,我有意识地避免使用perl包进行xml / html解析或清理工具。我正在处理的输入不是严格的html,我不想包含依赖项。
答案 0 :(得分:2)
我相信这符合您的要求:
我更换了&#39; a&#39;在正则表达式中使用[a-z] +,捕获并反向引用它。这意味着您必须更改应用它的行代替$2
。
如果您想要列出已接受的标签(这对我来说似乎更好,但我不知道您的用例),您可以将[a-z]+
替换为例如可接受标签列表由|
加入。
$expr = qr{
<\s*([a-z]+)(?:\s*|\s+[^>]+)>
((?:
(?> (?:(?!(<\s*\1(?:\s*|\s+[^>]+)>|<\/\s*\1\s*>)).)+ )
|
(??{ $expr })
)*)
<\/\s*\1\s*>
}x;
带有标记的简短示例脚本:
#!/usr/bin/env perl
use strict;
use warnings;
my $expr;
$expr = qr{
<\s*([a-z]+)(?:\s*|\s+[^>]+)>
((?:
(?> (?:(?!(<\s*\1(?:\s*|\s+[^>]+)>|<\/\s*\1\s*>)).)+ )
|
(??{ $expr })
)*)
<\/\s*\1\s*>
}x;
my $tmp_text = 'a<b> e </b>c<b href="test">g <b> d</b> d</b>f';
print $tmp_text."\n";
print $tmp_text."\n" while $tmp_text =~s/$expr/$2/g;
Wiktor在评论中发布了一个正则表达式,也允许使用大写字母和&#39; _&#39; - 如果这是您想要的,只需将[a-z]
替换为[a-zA-Z_]
,就像他的例子一样。