Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
||
ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
[3.133.141.6] |
|
Сообщ.
#1
,
|
|||
|
Пишу
Есть такой кусок кода (см. примечания ниже): foreach (@conv_table) { $line =~ s/$$_[0]/$$_[1]/ig; } @conv_table содержит в каждом члене (или элементе, если вам так угодно) пару: регулярное выражение и строка для подстановки, включающая $1, $2, ... (по необходимости). К примеру,
Проблема заключается в том, что вместо найденных значений подставляются $1, $2,... |
Сообщ.
#2
,
|
|
|
А можно код?
|
Сообщ.
#3
,
|
|
|
Попробу с eval:
foreach (@conv_table) { eval "\$line =~ s/\$\$_[0]/" . $$_[1] . "/ig"; } |
Сообщ.
#4
,
|
|
|
"Выкрутился" временным решением, указав подстановки прямо в коде. Но это неверный подход и я ещё расчитываю на простое решение.
Пробовал применить eval, но выдаётся много сообений "Use of uninitialized value in concatenation (.) or string at ..." Привожу исходный код для примитивного перевода программы с Object Pascal/Delphi в Component Pascal. Основная таблица замен выражений описана в файле Pas2Cp.txt. #!/usr/bin/env perl use strict; use warnings; my (@conv_table, $x); open(my $in, "<", "Pas2Cp.txt") or die "Can't open file with definitions!"; while (<$in>) { chomp; my ($expr, $repl) = split /\t/; push(@conv_table, [$expr, $repl]); } close $in or die "$in: $!"; while (<>) { chomp; my $line = $_; $line =~ s/\/\/(.*)$/(* $1 *)/ig; $line =~ s/\$([0-9A-F]+?)\b/0$1H/ig; $line =~ s/\#(\d+?)\b/0$1X/ig; $line =~ s/\barray\s*\[(.+?)\]/ARRAY $1 /ig; $line =~ s/\^([A-Za-z_]+)/POINTER TO $1/ig; $line =~ s/Result\s*:=\s*([^;]+?)/result := $1/ig; $line =~ s/FreeMem\((.+)\)/$1 := NIL/ig; $line =~ s/Dispose\((.+)\)/$1 := NIL/ig; foreach (@conv_table) { $line =~ s/$$_[0]/$$_[1]/ig; #~ eval "\$line =~ s/$$_[0]/" . $$_[1] . "/ig"; # эта строка приводит к ошибкам } print "$line\n"; } В общем, код справляется с поставленной задачей, но хотелось бы избавиться от строк $line =~ s///ig; |
Сообщ.
#5
,
|
|
|
my $str = <<'.' ; У попа была собака, он её любил. Затем, она съела кусок мяса. . while ( <DATA> ) { next unless m{^(.*?)\t+([^\r\n]+)}os ; my ( $rx , $expr ) = ( qr($1)is , $2 ) ; $str =~ s{$rx}{$expr}egex; } print ( $str ) ; __DATA__ п(.).+?(л)$1 . $2 . $1 . $2 . $1 . substr( $' , 0, 1 ) к $& . 'у' . $& . 'уш' . $& . 'а' |
Сообщ.
#6
,
|
|
|
Tishaishii, к чему этот код?
|
Сообщ.
#7
,
|
|
|
К теме.
|
Сообщ.
#8
,
|
|
|
Цитата Tishaishii @ К теме. Поясни код, будь добр. |
Сообщ.
#9
,
|
|
|
test.pl
undef ( $/ ) ; # отключаю разделение потока. По-умолчанию делится на звенья по символу '\n'. my $str = <> ; # читаю входной поток while ( <DATA> ) { # читаю дополнительные данные из программного файла next unless m{ # разбираю дополнительные данные. Эквивалентно: chomp ( $_ ) ; split ( /\t+/os , $_ , 2 ) ; ^ # начало каждой строки (.*?) # любой набор символов до символа '\t', запомнить в $1 \t+ # набор символов '\t' в количестве >= 1 ([^\r\n]+) # набор символов '\r' и '\n' в количестве >= 1, запомнить в $2 }osx ; my ( $rx , $expr ) = ( qr($1)is , $2 ) ; # $1 представить как регулярное выражение, $2 - выражение для подстановки как строка. $str =~ s{$rx}{$expr}egex ; # провести замену в $str. Двойной флаг "e" указывает на то, что строку подстановки следует представлять как выполняемый код. } print ( $str ) ; # вывод результата в STDOUT # в результате произведутся последовательные преобразования исходной строки с помощью перечисленных регулярных выражений и строк для подстановки. __DATA__ п(.).+?(л) $1 . $2 . $1 . $2 . $1 . substr( $' , 0, 1 ) к $& . 'у' . $& . 'уш' . $& . 'а' применять можно так: perl test.pl test.txt test.txt - файл с исходным текстом. |