如果我有类似以下内容的HTML行:(\t表示制表符)
<P>\tSome text</P>
<P>\t\tSome text</P>
<P>\tSome text</P>
Run Code Online (Sandbox Code Playgroud)
使用正则表达式,如何将以上内容转换为:
<P><BLOCKQUOTE>Some text</BLOCKQUOTE></P>
<P><BLOCKQUOTE><BLOCKQUOTE>Some text</BLOCKQUOTE></BLOCKQUOTE></P>
<p><BLOCKQUOTE>Some text></BLOCKQUOTE></P>
Run Code Online (Sandbox Code Playgroud)
目前,我有:
for $line (@lines)
{
$line =~ s{^(<P>(?:<BLOCKQUOTE>)*)\t(.+?)((?:</BLOCKQUOTE>)*</P>)$}{$1<BLOCKQUOTE>$2</BLOCKQUOTE>$3}g;
}
Run Code Online (Sandbox Code Playgroud)
此处的棘手问题是要以某种方式输入尽可能多的替换标签。
我将进行多次传递,首先计数标签,然后再次遍历字符串以将其替换为正确数量的开-关替换标签(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;
}
}
Run Code Online (Sandbox Code Playgroud)
版画
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;
}
}
Run Code Online (Sandbox Code Playgroud)
笔记
就目前而言,它最多可<p>...</p>在字符串中包含一个段落(),而
while (my ($tabs) = /<p>(\t+)/g) { ... }
Run Code Online (Sandbox Code Playgroud)
(而不是if (...))似乎适用于多个段落。需要更多测试
计数本身使用=()=“ operator”。它在右侧添加了列表上下文,因此正则表达式返回匹配项列表,该匹配项分配给左侧的标量。这样我们得到了计数。
在这种情况下,$tabs仅由制表符组成,就可以
my $nt = split '', $tabs;
Run Code Online (Sandbox Code Playgroud)
(更新:真的my $nt = length $tabs;,和其他答案一样)
我仍然使用正则表达式,因为它不仅可以用于制表符,而且可以用于字符串,而不仅仅是制表符
该代码仅替换开头,之后的连续制表符<p>,而不替换字符串后面可能出现的任何制表符(我如何看待需求)。
这是通过在图案(以下选项卡提供了一种用于\t+)配有一个单一非标签字符,然后任何字符,[^\t].*?。因此,这与具有更多选项卡的字符串匹配,但仅替换了选项卡的前导“块”