如果我的 HTML 如下所示:( \t
表示制表符)
<P>\tSome text</P>
<P>\t\tSome text</P>
<P>\tSome text</P>
使用正则表达式,如何将上述内容转换为:
<P><BLOCKQUOTE>Some text</BLOCKQUOTE></P>
<P><BLOCKQUOTE><BLOCKQUOTE>Some text</BLOCKQUOTE></BLOCKQUOTE></P>
<p><BLOCKQUOTE>Some text></BLOCKQUOTE></P>
目前我有:
for $line (@lines)
{
$line =~ s{^(<P>(?:<BLOCKQUOTE>)*)\t(.+?)((?:</BLOCKQUOTE>)*</P>)$}{$1<BLOCKQUOTE>$2</BLOCKQUOTE>$3}g;
}
最佳答案
这里的棘手之处是以某种方式输入与选项卡一样多的替换标签。
我会进行多次传递,首先计算选项卡,然后再次检查字符串以用正确数量的开闭替换标签( BLOCKQUOTE
)替换它们。在这种情况下,单个正则表达式必然要复杂得多,因此更难调整和维护。
use warnings;
use strict;
use feature 'say';
my @test_strings = (
qq(<p>\t\ttwo tabs</p>),
qq(<p>\tone tab</p>),
qq(<p>no tab</p>),
qq(<div>\tnot paragraph</div>),
);
say for @test_strings; say '';
for (@test_strings)
{
if (my ($tabs) = /<p>(\t+)/) # capture consecutive tabs
{
my $nt = () = $tabs =~ /\t/g; # count them
my $ot = "<BLOCKQUOTE>" x $nt; # open-tag
my $ct = "</BLOCKQUOTE>" x $nt; # close-tag
s{<p> \t+ ([^\t].+?) </p>}{<p>$ot$1$ct</p>}x;
say;
}
}
打印
<p> two tabs</p>
<p> one tab</p>
<p>no tab</p>
<div> not paragraph</div>
<p><BLOCKQUOTE><BLOCKQUOTE>two tabs</BLOCKQUOTE></BLOCKQUOTE></p>
<p><BLOCKQUOTE>one tab</BLOCKQUOTE></p>
<p>no tab</p>
<div> not paragraph</div>
笔记
<p>...</p>
),而while (my ($tabs) = /<p>(\t+)/g) { ... }
(而不是
if (...)
)似乎适用于多个段落。需要更多测试 =()=
"operator" 。它将列表上下文强加在其右侧,因此正则表达式返回匹配列表,分配给其左侧的标量。这样我们就得到了计数。在这种情况下,
$tabs
只包含制表符,你可以简单地做 my $nt = split '', $tabs;
(更新:真的只是
my $nt = length $tabs;
,就像其他答案一样)我仍然使用正则表达式,因为它可以用于字符串,而不仅仅是选项卡,还有
<p>
之后,而不是字符串中后面可能出现的任何制表符(我如何看待要求)。这是通过在模式 (
\t+
) 中的制表符之后使用单个非制表符和任何字符 [^\t].*?
来提供的。因此,这匹配具有更多制表符的字符串,但仅替换制表符的前导“块” 关于regex - 如何使用 perl 正则表达式将制表符转换为块引号,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/58334004/