首页 > 解决方案 > 如何使用 sed 安全地查找和替换正则表达式匹配的每个实例?

问题描述

假设我有一个包含以下场景的 html 文件;

1. <p style="1">test</p>
2. <p style="2"><p style="3">test</p></p>
3. <p style="4">test</p><p style="5">test</p>
4. <td style="6"><p style="7">test</p></td>
5. <td style="8"><p style="9">test</p><p style="10">test</p></td>

我想开发一种方法来查找每个实例<p style="test">并将其替换为<p>. 我已经知道,如果我想找到每一个,我会使用正则表达式<p .+?>或类似的东西<p .+?(?=>)>,这会让我得到任何以<p 包含任何字符开头并以>.

到目前为止,这是我尝试过的;

sed -r 's/<p .+?>\b/<p>/' 虽然这适用于场景 1 和 4,但对于包含多个<p ...>.

sed -r 's/\b<p .+?>\b/<p>/'这根本行不通。

我不会列出我在这里尝试过的所有可能的事情,因为我认为它不会为精通 sed 的人带来任何有意义的数据。我对如何使用它以及它的功能知之甚少。

解决这个问题的最佳方法是什么?谢谢!

标签: regexbashsed

解决方案


正如评论中提到的,一个真正理解 HTML 的工具是一个比试图用正则表达式破解一些东西更好的选择。

使用从标签中去除样式属性的模块的示例perl脚本:HTML::TreeBuilderp

#!/usr/bin/env perl
use warnings;
use strict;
use HTML::TreeBuilder;
use Data::Dumper;

# Takes the HTML file to process as a command line argument; outputs on
# standard output.

my $tree = HTML::TreeBuilder->new_from_file($ARGV[0]);
die "Unable to parse '$ARGV[0]': $!\n" unless defined $tree;

# Remove style attributes from all p tags with one
foreach my $tag ($tree->look_down('style', qr//)) {
    $tag->attr('style', undef) if $tag->tag eq 'p';
}

print $tree->as_HTML(undef, ' ');

推荐阅读