这比similar questions更复杂(对我来说!)。
我尝试将某些日期与一些旧HTML中的Regex复制到另一个位置,但是当我重复搜索并替换时,在所需块之外扩展的替换有问题。
在下面的示例中,每个块< ul> ..< / ul>表示第一个< li> ..< b>中包含的特定日期。我要复制" 2005年10月13日"进入随后的< li> ..< b>,同样地," 2005年10月14日"进入随后的< li> ..< b>也是,但不在其之外< ul> ..< / ul>块。
我可以使用以下正则表达式(由Funduc的Windows搜索和替换实用程序使用,显然是#34; UNIX grep表示法的一个子集)":
Search: <li>+[0-9] *<b>*[]<li><b>
Replace: <li>%1 %2\<b>%3\<li>%1 %2\<b>
+ [0-9]是一个或多个数字; *是按字母顺序排列的; * []是任何东西; %1 ..%4是替换位置。
这是我的原始HTML
<ul>
<li>13 Oct 2005<b>Title One</b>
Some text
<p>
<li><b>Title Two</b>
Some more text
<p>
</ul>
<ul>
<li>14 Oct 2005<b>Title 3</b>
Another line of text
<p>
<li><b>Title 4</b>
Yet another line of text
<p>
<li><b>Title 5</b>
Some text
<p>
</ul>
在我的第一个脚本运行后,这正确地给了我:
<ul>
<li>13 Oct 2005<b>Title One</b>
Some text
<p>
<li>13 Oct 2005<b>Title Two</b>
Some more text
<p>
</ul>
<ul>
<li>14 Oct 2005<b>Title 3</b>
Another line of text
<p>
<li>14 Oct 2005<b>Title 4</b>
Yet another line of text
<p>
<li><b>Title 5</b>
Some text
<p>
</ul>
但在我的第二个脚本运行后,2005年10月13日被错误地添加到下一个&lt; ul&gt; ..&lt; ul&gt;块:
<ul>
<li>13 Oct 2005<b>Title One</b>
Some text
<p>
<li>13 Oct 2005<b>Title Two</b>
Some more text
<p>
</ul>
<ul>
<li>14 Oct 2005<b>Title 3</b>
Another line of text
<p>
<li>14 Oct 2005<b>Title 4</b>
Yet another line of text
<p>
<li>13 Oct 2005<b>Title 5</b> <-- wrong !!!
Some text
<p>
</ul>
我有大约20,000个&lt; ul&gt; ..&lt; ul&gt;块(因此脚本),并且每个块包含1-10&lt; li&gt;&lt; b&gt;之间的块。带标题的标签。我以为它不可能一次完成。
答案 0 :(得分:0)
tl; dr正则表达式是错误的工具;用更强的东西。
使用正则表达式解析HTML是bad idea。它甚至在SO正则表达式引用中:Reference - What does this regex mean?
所以不要这样做。
如果你完全负责你的HTML文件,并且你不想要通用工具或任何东西,我不能阻止你使用正则表达式。
正如您所注意到的,单个正则表达式是错误的工具。至关重要的是,正则表达式,即使是具有反向引用和前瞻功能的强大表达式,也没有额外记忆他们不看的内容。
但这正是你在这里所要求的!您想知道您是否已离开<ul>
块,同时仅查看用于界定您要搜索的内容的日期和标记。
您需要的是一种编程语言。
您使用的正则表达式语法与unix样式的正则表达式语法完全不同。这是可以原谅的。
对于任何正则表达式爱好者而言,不可原谅的是使用多行正则表达式而不解释为什么必要。
啊哈!可是等等!现在我们已经得出结论,我们需要一种编程语言,不再需要多行正则表达式!
所以,让我们停止使用它们。
此时,我在这里是为了自我鞭挞:我得出结论,一方面,我们需要一种编程语言,因为我们需要比正则表达更强的东西;另一方面,我不会使用HTML解析器,因为我发誓我只使用正则表达式。
我显然是个白痴,你不应该听我说的任何话。
一旦我们允许自己使用编程语言,我们就可以一次性修复文件。我们只需要保存一个小状态:当前<ul>
块中的日期。
这是一个符合我为自己设定的可怕目标的Perl脚本(我使用的是5.22):
#! /usr/bin/perl
use strict;
use warnings;
my $date_re = qr/^<li>(\d+ [[:alpha:]]+ \d+)<b>/;
my $non_date_title_re = qr/^<li>(<b>.*<\/b>)$/;
my $local_date = '';
while (<>) {
if (/<\/ul>/) {
$local_date = '';
} elsif (/$date_re/) {
$local_date = $1;
} elsif (/$non_date_title_re/) {
s/$non_date_title_re/<li>$local_date$1/;
}
print;
}
你可能不会阅读Perl,但这里发生的事情非常清楚:首先,为了清晰起见,在局部变量中保存一些正则表达式:一个用于<li>
和<b>
之间的日期,一个用于标题没有约会。
对于文件中的每一行,如果它包含</ul>
,则会使我们保存的本地日期无效。 (对于您问题中的文件,此部分并非绝对必要。)如果该行与日期正则表达式匹配,请保存日期以供日后使用。如果该行与非日期图块匹配,请使用替换将我们保存的日期放在<li>
之后。
但实际上,请使用HTML解析器。