Хитрость в том, чтобы как-то ввести столько тегов замены, сколько есть вкладок.
Я бы сделал несколько проходов, сначала посчитав вкладки, а затем снова пройдя по строке, чтобы заменить их нужным количеством открытых-закрытых замещающих тегов (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 (...)
), кажется, работаетс несколькими параграфами. Требуется дополнительное тестирование
Для подсчета используется =()=
«оператор» . Он накладывает контекст списка на его правую сторону, поэтому регулярное выражение возвращает список совпадений, назначенных скаляру слева. Таким образом, мы получаем количество.
В этом случае, когда $tabs
состоит только из символов табуляции, можно просто сделать
my $nt = split '', $tabs;
(Обновление: на самом деле просто my $nt = length $tabs;
, так какв других ответах)
Я все еще использую регулярное выражение, так как оно будет работать для строки с вещами, отличными от просто вкладок, а также
Код заменяет только последовательныйвкладки в начале, сразу после <p>
, а не те, которые могут появиться позже в строке (как я вижу требование).
Это обеспечивается путем следования вкладкам в шаблоне (\t+
)с одиночным символом без табуляции и затем любыми символами [^\t].*?
. Таким образом, это соответствует строке с большим количеством вкладок ниже, но заменяет только начальный «блок» вкладок