0

我有一个 HTML 文件文件夹,其中包含我需要删除的以下 DOCTYPE 声明,以便不太好的解析器可以成功地将其加载为 XML。

我一直在尝试使用 perl 进行替换,但是当我运行替换时没有进行任何更改,我不知道为什么。任何人都可以识别我需要制作的正确标志或规范,以便在此处删除 DOCTYPE 处理指令。

这是我想操作的示例文件。

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">
<head>
  <meta name="generator" content=
  "HTML Tidy for Linux/x86 (vers 25 March 2009), see www.w3.org" />
  <title></title>
</head>
  <body>
  </body>
</html>

这是我正在尝试使用的 perl 单行代码,它查找尖括号、感叹号以及右尖括号之前的所有内容。它包含 perl 替换标志,其他帖子建议应该适用于多行匹配 - m 用于多行,s 用于允许换行符与正则表达式匹配。然后我用空字符串替换匹配项。

perl -i -e 's/<![^>]+>//gsm' `find . -name '*.html'`

我不知道为什么,但运行此命令后 DOCTYPE 并未从文件中删除。还有人知道为什么吗?

4

2 回答 2

1

您需要的是-0777将整个文件读入单个字符串的开关。如果不使用,文件将以逐行模式读取,并且您永远无法以这种方式匹配多行语句。

此外,正如 Andomar 指出的那样,您缺少-p开关,但我假设您已经弄清楚了。

在这种情况下,正则表达式上的修饰符无关紧要,除了/g修饰符。/m仅影响^and $,并/s导致通配符.也匹配换行符。这些都不适用于您的正则表达式。

所以基本上,你想要这样的东西:

perl -0777 -pi -e 's/<![^>]+>//g' ...

边注:

理想情况下,HTML 应该使用解析器来处理,所以我花了几分钟的时间来使用HTML::Parser它,它有一个方便的选项,可以通过添加处理程序来剥离声明。对于单个文件,这样的东西似乎可以打印:

perl -MHTML::Parser -we '
    $p = HTML::Parser->new(default_h => [sub {print @_},'text'] ); 
    $p->handler(declaration => ''); 
    $p->parse_file(shift) or die $!; " yourfile.html

我认为这太过分了,所以我放弃了尝试使用-pi就地编辑开关来修复它,但它(可能)很容易在脚本中实现。

于 2013-05-03T12:29:24.380 回答
1

首先,您似乎缺少-p用于逐行处理输入的参数。 -i没有-p.

其次,由于-pi逐行处理输入,它不能替换跨越多行的正则表达式。

您可以改为编写 Perl 脚本。此脚本应在命令行上传递的所有文件的全部内容上运行您的正则表达式:

use IO::All;

foreach my $file (@ARGV) {
    my $content = io($file)->slurp;
    $content =~ s/<![^>]+>//g;
    $content > io($file);
}

如果您的系统上不存在该模块,该命令cpan IO:All应该安装该模块。IO:All

PS mands选项只影响.,^$。我认为你可以省略它们。

于 2013-05-03T11:22:46.693 回答