На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
! Внимательно изучите правила раздела перед созданием темы
0. ПРИЛАГАЙТЕ СВОИ СКРИПТЫ.
1. Прежде чем создать топик, используйте поиск. Возможно это уже обсуждалось.
2. В топике указывайте ОС, режим работы скрипта (CLI|CGI). Очень желателен вывод лог-файлов и того места, куда у вас назначен вывод данных (STDOUT|STDERR)
3. Помните: вы знаете что вы хотите, а форумчане - нет. Поэтому следуйте простому правилу: грамотный развернутый вопрос - грамотный развернутый ответ.
Модераторы: ANDLL
  
    > "Хитрые" подстановки
      Пишу тупой примитивный и незаковыристый транслятор с одного языка на другой, используя файл с описаниями регулярных выражений и их подстановок.

      Есть такой кусок кода (см. примечания ниже):
      ExpandedWrap disabled
            foreach (@conv_table) {
                $line =~ s/$$_[0]/$$_[1]/ig;
            }


      @conv_table содержит в каждом члене (или элементе, если вам так угодно) пару: регулярное выражение и строка для подстановки, включающая $1, $2, ... (по необходимости). К примеру,
      \$(\d+)0$1H


      Проблема заключается в том, что вместо найденных значений подставляются $1, $2,...
        А можно код?
          Попробу с eval:

          ExpandedWrap disabled
                      foreach (@conv_table) {
                          eval "\$line =~ s/\$\$_[0]/" . $$_[1] . "/ig";
                      }
            "Выкрутился" временным решением, указав подстановки прямо в коде. Но это неверный подход и я ещё расчитываю на простое решение.
            Пробовал применить eval, но выдаётся много сообений "Use of uninitialized value in concatenation (.) or string at ..."

            Привожу исходный код для примитивного перевода программы с Object Pascal/Delphi в Component Pascal. Основная таблица замен выражений описана в файле Pas2Cp.txt.
            ExpandedWrap disabled
              #!/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;
            Сообщение отредактировано: Romtek -
              ExpandedWrap disabled
                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 )
                к          $& . 'у' . $& . 'уш' . $& . 'а'
                Tishaishii, к чему этот код?
                  К теме.
                    Цитата Tishaishii @
                    К теме.

                    Поясни код, будь добр.
                      test.pl
                      ExpandedWrap disabled
                        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 )
                        к           $& . 'у' . $& . 'уш' . $& . 'а'


                      применять можно так:
                      ExpandedWrap disabled
                        perl test.pl test.txt


                      test.txt - файл с исходным текстом.
                      Сообщение отредактировано: Tishaishii -
                      0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
                      0 пользователей:


                      Рейтинг@Mail.ru
                      [ Script execution time: 0,0284 ]   [ 16 queries used ]   [ Generated: 28.03.24, 11:49 GMT ]