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


Автор: tolkien 5.5.2008, 05:16
Доброе утро! Возникла проблема с подстановкой. Операнд замены интерпретируется только один раз. 

Листинг 1
Код

my $m1 = '(\d+) (\d+),(\d+)'; 
my $m2 = '$1$2.$3'; 

my $s = '15 148,02';

$s =~ s/$m1/$m2/;

Получаю вместо 15148.02       $1$2.$3

Пока нашел только такое решение. 

Листинг 2
Код

my $m1 = '(\d+) (\d+),(\d+)'; 
$m2 = '$1.$2.".".$3';

my $s = '15 148,02';

$s =~ s/$m1/$m2/ee;


Можно как нибудь явно указывать что необходима еще дополнительная интерпретация? И решить данную задачу без внесении изменений в шаблон $m2 Листинг1?

P.S решение такого вида $s =~ s/$m1/$1$2.$3/ не подходит т.к шаблоны загружаются из внешнего файла.




Автор: FooBar 5.5.2008, 06:41
модификатор g?
хотя похоже вы не об этом..

Автор: amg 5.5.2008, 06:47
Цитата(tolkien @  5.5.2008,  05:16 Найти цитируемый пост)
... решить данную задачу без внесении изменений в шаблон $m2 Листинг1?
Код
$s =~ s/$m1/qq("$m2")/ee;


Автор: sir_nuf_nuf 5.5.2008, 07:57
можно.
Для того что бы ссылаться на строки, захваченые в () ВНУТРИ регулярного выражения нужно использовать не $1 $2 а \1 \2

пример
Код

$a = "abc123def";
$a =~ s/(\d)(\d)(\d)/\3\2\1/;
print $a;



результат
Код

abc321def




в вашем случае:
Код

$s =~ s/(\d+) (\d+),(\d+)/\1\2.\3/;

Автор: amg 5.5.2008, 08:29
Цитата(sir_nuf_nuf @  5.5.2008,  07:57 Найти цитируемый пост)
Для того что бы ссылаться на строки, захваченые в () ВНУТРИ регулярного выражения нужно использовать не $1 $2 а \1 \2
sir_nuf_nuf, если иметь в виду поисковую часть оператора s///, то Вы совершенно правы. А в заменяющей части этого оператора (а также вне регулярного выражения) использовать нотацию \1 \2 нет смысла. Оно там лишь для совместимости с sed и пр. С use warnings перл даже поругается в том смысле, что $1 лучше, чем \1. К тому же, замена $1 на \1, насколько я понимаю, никак не решает проблему, поставленную топикстартером. Кроме того, такая замена противоречит условию задачи (не трогать $m2).

Автор: tolkien 5.5.2008, 14:03
FooBar
Точно модификатор /g здесь не в теме

sir_nuf_nuf
Замена $1 на \1 не решает проблему. Ничего не меняется. 

amg
Спасибо работает.

Автор: amg 5.5.2008, 15:58
Цитата(tolkien @  5.5.2008,  05:16 Найти цитируемый пост)
Можно как нибудь явно указывать что необходима еще дополнительная интерпретация?
tolkien, не уверен, но мне кажется, что интерполяция /eeнеобходима и достаточна. 

Другой вопрос - автоматическое определение вида заменяющей части. Например
Код

$m2 = '$1+$2+$3'; # если такое выражение
$s =~ s/$m1/$m2/ee; # то нужно так

$m2 = '$1$2$3'; # а если такое
$s =~ s/$m1/qq("$m2")/ee; # то по другому
Возможно, есть еще варианты. Вопрос интересный и актуальный. Если у Вас или других форумчан есть универсальное решение, буду благодарен за его публикацию. И сам подумаю.

Автор: AlexPet 6.5.2008, 16:21
amg, мне кажется, будет зависеть от того, чего хочет человек, пишущий заменяющее выражение.
Написав ".", он хочет вывести символ "точка" или конкатенировать строки?
А написав "+", он хочет сложить числа или вывести знак "плюс"?
Получается, что избрав "вывод символов как они есть" - нам нужно сначала интерполировать переменные, и уж потом делать все остальное - и поэтому принудительно делаем двойную вложенность кавычек - с помощью qq("выражение").
Если же хотим "выполнять" символы - то достаточно просто дважды выполнить заменяющую часть.

P.S. Спасибо за интересное замечание, раньше я об этом не задумывался smile

Автор: tishaishii 6.5.2008, 16:59
А откуда этот шаблон подстановок перётся?
Есть два варианта: при вводе шаблона использовать флаг типа вычислять чи ни или разработка отдельного синтаксиса, скорее всего, совпадающего с перл для евала, который описывает действия при подстановке.

Автор: amg 7.5.2008, 08:21
Цитата(AlexPet @  6.5.2008,  16:21 Найти цитируемый пост)
amg, мне кажется, будет зависеть от того, чего хочет человек, пишущий заменяющее выражение...
Да, конечно. И именно поэтому мой вопрос на самом деле не имеет смысла и аннулируется.

Автор: tolkien 9.5.2008, 20:43
У меня опять вопрос по интерполяции. Только уже в операторе поиска. Условия как прежде из внешнего файла считываются шаблоны. Только в этом случаи ненужно ничего заменять нужно только выдернуть данные. Решение нашел в гугле. Можно ли выполнить итерполяцию в этой строчке $res = eval "\"$m2\""; ,без использования eval?

Листинг3
Код


my $m1 = '(\d*\.?\d+) (\S+)';
my $m2 = '$2 $1'; 

my $s = '15.02 mm';

if ($s =~ m/$m1/)
{
   $res = eval "\"$m2\"";
}

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