2012-03-22 2 views
0

Итак, я, наконец, получил, что мой босс одобрил использование perl для этой цели, а не sed.Perl non-greedy Regex

Вот базовое quandry.

У меня есть такие строки:

<div class="SectionText">Sometext</div><div class="SectionText">Some more text</div> 

Это ужасно грязный, но я не писал. В любом случае, есть изрядное количество страниц, как это, и они должны быть изменены в следующем формате:

<p>Sometext</p><p>Some more text</p> 

Очевидно, что это должно быть не жадный. Теперь вот линия, которую я придумал, чтобы помочь с этим:

perl -nle "s/(.*)<div class=\"SectionText\">(.*?)<\/div>(.*)/\1<p>\2<\/p>\3/ig; print $1" "somefile.html" > otherfile.html 

Однако это не делает ничего, и все SectionText теги по-прежнему остаются.

+0

Вы говорите, что это должно быть не жадным и все же поставить '. *' В начале, посередине и в конце регулярного выражения. Кроме того, вы уверены, что не хотите использовать для этого фактический парсер HTML? –

ответ

6

Помните, что регулярные выражения далеко не идеальны для обработки HTML. Правильный способ - использовать парсер и манипулировать DOM, но вы можете уйти с регулярными выражениями для простых и хороших ситуаций. Просто имейте в виду, что это слабое место в вашем дизайне и может вызвать непредвиденные проблемы.

Нет необходимости снимать и восстанавливать текст вне области редактирования. Просто замените элемент <div> на элемент <p> с тем же содержимым. Также нет необходимости избегать двойных кавычек или слэшей, пока вы выбираете разные разделители.

Также неверно использовать \1, \2 и т. Д. В заменяющей строке. $1, $2 и т. Д., И вы были бы предупреждены об этом, если бы вы использовали -w в командной строке.

Это должно работать для вас

perl -pe 's|<div class="SectionText">(.*?)</div>|<p>$1</p>|ig' somefile.html > otherfile.html 
+0

Спасибо! Это работает отлично! –

4

См HTML::TreeBuilder::XPath и HTML::Element методов вывода.

my $t = HTML::TreeBuilder::XPath 
    ->new_from_content('<div class="SectionText">Sometext</div><div class="SectionText">Some more text</div>'); 
for ($t->findnodes('//div[@class="SectionText"]')) { 
    $_->tag('p'); 
    $_->attr(class => undef); 
} 

Чтобы сделать 100% правильно, значение class атрибут должен быть разделен на белом пространстве, имя класса SectionText удаляется, а значение атрибута повторно собраны. Я думаю, что в вашем случае вы можете уйти, просто удалив атрибут class, как в приведенном выше коде.