Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Perl: Регулярные выражения > замена содержимого между тегами


Автор: ImSave 10.11.2009, 14:20
Всем привет. Подскажите новичку пожалуйста.
В переменной $c_cont содержится текст вида:
Код

..бла бла бла.. ... <a  бла бла1 </a>.... <a бла бла2 </a>...

нужно текст между всеми тегами <a ...</a> заменить на слово: ссылка
т.е. должно получится
Код

..бла бла бла.. ... <a ссылка </a>.... <a ссылка </a>...

Автор: Pfailed 10.11.2009, 16:13
Что может быть проще
Код

s@(?<=<a ).+?(?= </a>)@ссылка@gs

Автор: sir_nuf_nuf 10.11.2009, 17:25
как же всем нравится использовать всякие символы за место слешей в качесве разделителей реджексов...
жаль вим тупит на таких конструкциях

Автор: Pfailed 10.11.2009, 18:05
Я обычно использую слеши. Но когда сами слеши встречаются в выражении, то дабы не плодить частокол, очевидно есть резон воспользоваться альтернативными разделителями.

Автор: ImSave 10.11.2009, 18:44
Цитата(Pfailed @ 10.11.2009,  16:13)
Что может быть проще
Код

s@(?<=<a ).+?(?= </a>)@ссылка@gs

Спасибо! 
а т.к. может встречаться и <A ...</A> 
то правильнее и быстрее ли будет вместо этих двух строк:
Код

my $c_cont = s@(?<=<a ).+?(?= </a>)@ссылка@gs
my $c_cont = s@(?<=<А ).+?(?= </А>)@ссылка@gs

использовать:
Код

my $c_cont = s@(?<=<[Aa] ).+?(?= </[Aa]>)@ссылка@gs

??

Автор: Pfailed 10.11.2009, 19:07
В таком случаи я бы сделал так:
Код

s@(?<=<a ).+?(?= </a>)@ссылка@gsi


модификатор i - игнорировать регистр.

Автор: krypt3r 11.11.2009, 07:09
И что вы этим кодом
Код

my $c_cont = s@(?<=<А ).+?(?= </А>)@ссылка@gs

получите? В переменной $c_cont у вас будет число произведенных замен в переменной $_. Поставьте тильду после знака равенства

Автор: Bulat 11.11.2009, 09:04
Цитата(Pfailed @  10.11.2009,  18:05 Найти цитируемый пост)
Я обычно использую слеши. Но когда сами слеши встречаются в выражении, то дабы не плодить частокол, очевидно есть резон воспользоваться альтернативными разделителями. 


Разве что символ '@' - не самый приятный разделитель. ИМХО, есть фигурные скобки. smile

Автор: ImSave 11.11.2009, 12:40
Цитата(krypt3r @ 11.11.2009,  07:09)
И что вы этим кодом
Код

my $c_cont = s@(?<=<А ).+?(?= </А>)@ссылка@gs

получите? В переменной $c_cont у вас будет число произведенных замен в переменной $_. Поставьте тильду после знака равенства

Код

my $c_cont =~ s@(?<=<А ).+?(?= </А>)@ссылка@gs

оно?

Добавлено через 6 минут и 4 секунды
Цитата(Bulat @ 11.11.2009,  09:04)
Разве что символ '@' - не самый приятный разделитель. ИМХО, есть фигурные скобки. smile

у вас есть другое предложение?
можете пример для моего случая показать?

Автор: krypt3r 11.11.2009, 14:03
Если у вас исходный текст находится в переменной $c_cont, то Pfailed уже написал, как делается
Код

$c_cont =~ s@(?<=<a ).+?(?= </a>)@ссылка@gsi;

Какой символ юзать, имхо, без разницы. Кому как нравится. В "классическом написании" будет так
Код

$c_cont =~ s/(?<=<a ).+?(?= <\/a>)/ссылка/gsi;

С фигуристыми скобками =)
Код

$c_cont =~ s{(?<=<a ).+?(?= </a>)}{ссылка}gsi;


Автор: ImSave 12.11.2009, 15:15
спасибо всем огромное! все получилось.
только перед </a> не должно быть пробела
т.е.
Код

s@(?<=<a ).+?(?=</a>)@ссылка@gsi;


и еще вопросик.
Это оптимальный вариант в плане скорости???

Автор: Bulat 13.11.2009, 12:54
Цитата(ImSave @  12.11.2009,  15:15 Найти цитируемый пост)
только перед </a> не должно быть пробела

пробелы я советовал бы обрабатывать через \s*. По своему опыту - это такой хитрый символ, что иной раз встречается там где казалось бы быть не должен, или наоборот, может и не оказаться где ожидалось.  smile

Добавлено через 1 минуту и 3 секунды
А еще бывает, что иногда вместо одного пробела, иной раз может оказаться больше smile

Автор: amg 13.11.2009, 13:35
Цитата(ImSave @  12.11.2009,  15:15 Найти цитируемый пост)
Это оптимальный вариант в плане скорости???
Скорее всего, быстрее (но вряд ли сильно) будет вариант без использования заглядываний внеред/назад:
Код
$c_cont =~ s|<a\s.+?</a>|<a ссылка</a>|gsi;


Автор: ImSave 13.11.2009, 13:47
ок. Попробую.
А можете привести ф-ю с помощью которой можно сравнить скорость работы этого. Ну типа:
Код

print TimeStart();
$c_cont =~ s|<a\s.+?</a>|<a ссылка</a>|gsi;
print TimeStop();

до миллисекунд желательно...ну или как еще сравнить скорость выполнения этих вариантов.

Автор: ginnie 13.11.2009, 13:53
ImSave, попробуй

Код

use Time::HiRes 'time';

print time(), $/;


Но не думаю, что разница будет заметной.

Автор: amg 13.11.2009, 14:44
На самом деле разница разница весьма ощутима: 

$c_cont = 'содержится текст вида:код PHP
1:
        ..бла бла бла.. ... <a  бла бла1 </a>.... <a бла бла2 </a>...';


$_=$c_cont, s|(?<=<a ).+?(?=</a>)|ссылка|gsi for 1..1e6;
15 c

$_=$c_cont, s|<a\s.+?</a>|<a ссылка</a>|gsi for 1..1e6;
4 c

$_=$c_cont for 1..1e6;
0.4 с

Но будет ли в реальной жизни миллион замен?

Автор: ImSave 13.11.2009, 20:19
Цитата(ginnie @ 13.11.2009,  13:53)
Но не думаю, что разница будет заметной.

Код

1258131742.0206
если это такой формат времени...то судя по нему ваш вариант быстрее примерно в 1.5 раза
но и бывает что время перед форматированием и после абсолютно совпадает. Это как так?

Автор: Bulat 17.11.2009, 16:38
Цитата(ImSave @  13.11.2009,  20:19 Найти цитируемый пост)
если это такой формат времени...то судя по нему ваш вариант быстрее примерно в 1.5 раза
но и бывает что время перед форматированием и после абсолютно совпадает. Это как так? 


попробуй заюзать 
Код

...
use re 'debug'; 
...


поможет узнать много интересного о конкретно составленном регулярном выражении smile

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)