Встраивание оценок в Perl regex

Таким образом, я пишу быстрый сценарий жемчуга, который очищает некоторый HTML-код и выполняет его через HTML-> программа PDF. Я хочу потерять как можно меньше информации, таким образом, я хотел бы расширить свои текстовые области для установки всему тексту, который в настоящее время находится в них. Это означает, в моем случае, определяя номер строк к расчетному значению на основе значения строки в текстовом поле.

Это в настоящее время - regex, который я использую

$file=~s/<textarea rows="(.+?)"(.*?)>(.*?)<\/textarea>/<textarea rows="(?{ length($3)/80 })"$2>$3<\/textarea>/gis;

К сожалению, Perl, кажется, не распознает то, что мне сказали, был синтаксис для встраивания кода Perl в поиске-и-замене regexs там, какие-либо наркоманы Perl там готовы сказать мне, что я делаю неправильно? С уважением, Zach

8
задан Zach H 14 July 2010 в 22:05
поделиться

5 ответов

Шаблон (?{...}) является экспериментальной функцией для выполнения кода на стороне соответствия, но вы хотите выполнять код на стороне замены. Для этого используйте переключатель регулярного выражения /e:

#! /usr/bin/perl

use warnings;
use strict;

use POSIX qw/ ceil /;

while (<DATA>) {
  s[<textarea rows="(.+?)"(.*?)>(.*?)</textarea>] {
    my $rows = ceil(length($3) / 80);
    qq[<textarea rows="$rows"$2>$3</textarea>];
  }egis;
  print;
}

__DATA__
<textarea rows="123" bar="baz">howdy</textarea>

Выход:

<textarea rows="1" bar="baz">howdy</textarea>
11
ответ дан 5 December 2019 в 09:24
поделиться

Синтаксис, который вы используете для вставки кода, действителен только в части подстановки "совпадение" (левая часть). Чтобы вставить код в правую часть (которая является обычной строкой Perl с двойными кавычками), вы можете сделать следующее:

$file =~ s{<textarea rows="(.+?)"(.*?)>(.*?)</textarea>}
          {<textarea rows="@{[ length($3)/80 ]}"$2>$3</textarea>}gis;

Здесь используется идиома Perl "some string @{[ embedded_perl_code() ]} more string".

Но если вы работаете с очень сложным выражением, может быть проще перевести подстановку в режим "eval", где она будет рассматривать заменяющую строку как код Perl:

$file =~ s{<textarea rows="(.+?)"(.*?)>(.*?)</textarea>}
          {'<textarea rows="' . (length($3)/80) . qq{"$2>$3</textarea>}}gise;

Обратите внимание, что в обоих примерах regex структурирован как s{}{}. Это не только избавляет от необходимости экранировать косые черты, но и позволяет распределить выражение по нескольким строкам для удобства чтения.

6
ответ дан 5 December 2019 в 09:24
поделиться

Это нужно делать с помощью регулярного выражения? Анализ любого языка разметки (или даже CSV) с помощью регулярного выражения чреват ошибкой. Если можете, попробуйте использовать стандартную библиотеку:

http://search.cpan.org/dist/HTML-Parser/Parser.pm

В противном случае вы рискуете отомстить Ктулу:

http: / /www.codinghorror.com/blog/2009/11/parsing-html-the-cthulhu-way.html

( Да, статья оставляет место для некоторых простых манипуляций со строками, так что я думаю, что ваша душа в безопасности, хотя .: -)

1
ответ дан 5 December 2019 в 09:24
поделиться

Я полагаю, что ваша проблема заключается в неэскейпированном /

Если это не проблема, то это определенно проблема.

Попробуйте это вместо этого, обратите внимание на \/80

$file=~s/<textarea rows="(.+?)"(.*?)>(.*?)<\/textarea>/<textarea rows="(?{ length($3)\/80 })"$2>$3<\/textarea>/gis;

Основной шаблон для этого кода:

$file =~ s/some_search/some_replace/gis;

gis - это опции, которые мне придется поискать. Думаю, g = глобальный, i = нечувствительный к регистру, s = ничего не приходит на ум.

0
ответ дан 5 December 2019 в 09:24
поделиться

Во-первых, вам нужно заключить в кавычки / внутри выражения в тексте замены (иначе perl увидит оператор s ///, за которым следует число 80 и так далее). Или вы можете использовать другой разделитель; для сложных замен рекомендуется использовать соответствующие скобки.

Затем вы переходите к основной проблеме, которая заключается в том, что (? {...}) доступен только в шаблонах. Текст замены - это не шаблон, это (почти) обычная строка.

Вместо этого есть модификатор e для оператора s /// , который позволяет писать выражение замены, а не строку замены.

$file =~ s(<textarea rows="(.+?)"(.*?)>(.*?)</textarea>)
          ("<textarea rows=\"" . (length($3)/80) . "\"$2>$3</textarea>")egis;
0
ответ дан 5 December 2019 в 09:24
поделиться
Другие вопросы по тегам:

Похожие вопросы: