Модераторы: korob2001, ginnie
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Замена символов между тэгами, регулярным выражением 
:(
    Опции темы
amg
Дата 12.7.2007, 13:02 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1145
Регистрация: 3.8.2006
Где: Новосибирск

Репутация: 38
Всего: 50



С виду простая задачка:
есть строка
$_ = 'aXbX<a>cXbX</a>eXgXaXbX<a>cXbX</a>eXgX';
нужно заменить X на У, но не везде, а только внутри тэгов.
Т.е. должно получиться
aXbX<a>cYbY</a>eXgXaXbX<a>cYbY</a>eXgX

Понятно, что можно выкусить нужные подстроки, сделать в них замены и вставить обратно, либо как-то так:
Код

s|(?<=<a>)(.+?)(?=</a>)|($a="$1")=~s/X/Y/g;$a|eg;

Но верится, что что так просто формулируемая задачка не решается обыкновенным регулярным выраженим, без выполнения дополнительного кода: что-то подобное уже было, и тогда нашлось потрясающе элегантное решение.
PM MAIL   Вверх
Nab
Дата 12.7.2007, 14:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 582
Регистрация: 25.3.2006
Где: Kiev

Репутация: 26
Всего: 37



У меня пока получилось вот такое
Код

s!(<a>[^<]*?|\G[^<]*?)X!$1Y!g;


Но учитывая что \G без предыдущего совпадения соответствует ^, то в подстроке желательно убрать лидирующий текст до первого тега...

Буду думать еще, может и нарисуюю работающий вариант...


--------------------
 Чтобы правильно задать вопрос нужно знать больше половины ответа...
Perl Community 
FREESCO in Ukraine 
PM MAIL   Вверх
Nab
Дата 12.7.2007, 15:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 582
Регистрация: 25.3.2006
Где: Kiev

Репутация: 26
Всего: 37



Сейчас есть решение, не в одну регулярку а в две smile
первой просто позиционирую первую pos для \G:
Код

m!^[^<]*!g;
s!(<a>[^<]*?|\G[^<]*?)X!$1Y!g;



--------------------
 Чтобы правильно задать вопрос нужно знать больше половины ответа...
Perl Community 
FREESCO in Ukraine 
PM MAIL   Вверх
JAPH
Дата 12.7.2007, 15:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 312
Регистрация: 8.1.2007
Где: Ленобласть

Репутация: 3
Всего: 23



У меня такое, которому далеко до совершенства:
Код
s#\G([^<X]*)X#$1Y#g while /<a>/g;



--------------------
Что непонятно - спрашиваем smile
PM MAIL ICQ   Вверх
JAPH
Дата 12.7.2007, 16:20 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 312
Регистрация: 8.1.2007
Где: Ленобласть

Репутация: 3
Всего: 23



Уложился в одну регулярку. Насколько элегантно - не знаю.. smile
Код
s#(^.*?<a>.*?|\G(?:[^<]*?|<(?!/a>))*?|\G.*?</a>.*?<a>.*?)X#$1Y#g;


Добавлено @ 16:25
Преимущества - применима к замене не только одного символа.
Недостатки - длинная smile + не понимает вложенных тегов

Это сообщение отредактировал(а) JAPH - 12.7.2007, 16:30


--------------------
Что непонятно - спрашиваем smile
PM MAIL ICQ   Вверх
amg
Дата 13.7.2007, 10:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1145
Регистрация: 3.8.2006
Где: Новосибирск

Репутация: 38
Всего: 50



NabJAPH, как всегда, на высоте! Спасибо большое. Может настанут, наконец, те светлые времена, когда и я буду понимать, как работает \G

Но я, как всегда, перемудрил с вопросом. Засада в том, что в на самом деле мне нужно заменять не X на Y, а < и > на &lt; и &gt; соответственно.
PM MAIL   Вверх
JAPH
Дата 13.7.2007, 13:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 312
Регистрация: 8.1.2007
Где: Ленобласть

Репутация: 3
Всего: 23



Так с этого и надо было начинать! (:
Ну, скорее, недомудрили smile
Одной регуляркой без 'e' уже не обойтись, так как возможностей замены две.
Код
s{(^.*?<a>|\G)((?:(?>[^<>]+)|</a>.*?<a>)*)(?:(</a>(?!<a>)(?>.*)$)|([<>]))}
 {$1.$2.($4 ? ($4 eq '<' ? '&lt;' : '&gt;') : $3)}ge;

Немного подумав
Хотя.. smile
Код

my %a = ('<' => '&lt;', '>' => '&gt;');
no warnings 'uninitialized';
s#(^.*?<a>|\G)((?:(?>[^<>]+)|</a>.*?<a>)*)(?:(</a>(?!<a>)(?>.*)$)|([<>]))#$1$2$a{$4}$3#g;


Это сообщение отредактировал(а) JAPH - 13.7.2007, 13:50


--------------------
Что непонятно - спрашиваем smile
PM MAIL ICQ   Вверх
amg
Дата 13.7.2007, 15:06 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1145
Регистрация: 3.8.2006
Где: Новосибирск

Репутация: 38
Всего: 50



JAPH, гениально! Твое решение даже легко вполне универсальным сделать. 
Код

my %a = ('<' => '&lt;', '>' => '&gt;');
my $r = join '', keys %a;
my $b = qr(\Q<a>\E); 
my $e = qr(\Q</a>\E);
no warnings 'uninitialized';
s/(^.*?$b|\G)((?:(?>[^$r]+)|$e.*?$b)*)(?:($e(?!$b)(?>.*)$)|([$r]))/$1$2$a{$4}$3/sg;
Мелочь, конечно, но приятно, что при этом можно использовать s/// - мой редактор только для такой конструкции регулярные выражения правильно раскрашивает.

PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Perl"
korob2001
sharq
  • В этом разделе обсуждаются общие вопросы по языку Perl
  • Если ваш вопрос относится к системному программированию, задавайте его здесь
  • Если ваш вопрос относится к CGI программированию, задавайте его здесь
  • Интерпретатор Perl можно скачать здесь ActiveState, O'REILLY, The source for Perl
  • Справочное руководство "Установка perl-модулей", можно скачать здесь


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, korob2001, sharq.

 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Perl: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0838 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.