The OpenNET Project / Index page

[ новости /+++ | форум | теги | ]




Версия для распечатки Пред. тема | След. тема
Новые ответы [ Отслеживать ]
STDOUT/STDERR обработать через функцию, !*! jr, 04-Июл-07, 17:23  [смотреть все]
Есть скрипт perl, который что-то выводит в STDOUT и в STDERR через print. Нужно не меняя print обработать этот вывод через функцию и перенаправить его куда-нибудь в другое место.
Как это сделать?
  • STDOUT/STDERR обработать через функцию, !*! andy, 06:10 , 05-Июл-07 (1)
    >Есть скрипт perl, который что-то выводит в STDOUT и в STDERR через
    >print. Нужно не меняя print обработать этот вывод через функцию и
    >перенаправить его куда-нибудь в другое место.
    >Как это сделать?

    если правильно понял задачу, то нечто вроде этого

    #!/usr/bin/perl
    use strict;
    use warnings;
    sub print_array;

    tie *STDOUT, 'OUT';
    tie *STDERR, 'OUT';

    print "qwe";
    warn "oops";
    print "asd";

    untie *STDERR;
    untie *STDOUT;

    print_array( OUT->get_buffer );

    sub print_array {
      print "res: $_\n" foreach( @_ );
    }

    #######################################################
    package OUT;
    our @buffer;

    sub TIEHANDLE { bless {} }
    sub UNTIE {}
    sub PRINT { push @buffer, $_[1]; }

    sub get_buffer { return @buffer; }
    sub clear_buffer { @buffer = (); }


    __END__


    что называется, quick and dirty, но как пример сойдет

    • STDOUT/STDERR обработать через функцию, !*! andy, 06:14 , 05-Июл-07 (2)
      да, ну и конечно perldoc perltie, perldoc -f tie, perldoc -f bless, ну и прочее

    • STDOUT/STDERR обработать через функцию, !*! jr, 09:34 , 05-Июл-07 (3)
      Спасибо, andy!
      Но не совсем полностью, что хотелось бы. В примере получается, что вывод будет осуществлен только после исполнения print_array( OUT->get_buffer ); Нужно другое - вывод срезу, после появления print или warn

      >если правильно понял задачу, то нечто вроде этого
      >
      >#!/usr/bin/perl
      >use strict;
      >use warnings;
      >sub print_array;
      >
      >tie *STDOUT, 'OUT';
      >tie *STDERR, 'OUT';
      >
      >print "qwe";
      >warn "oops";
      >print "asd";
      >
      >untie *STDERR;
      >untie *STDOUT;
      >
      >print_array( OUT->get_buffer );
      >
      >sub print_array {
      >  print "res: $_\n" foreach( @_ );
      >}
      >
      >#######################################################
      >package OUT;
      >our @buffer;
      >
      >sub TIEHANDLE { bless {} }
      >sub UNTIE {}
      >sub PRINT { push @buffer, $_[1]; }
      >
      >sub get_buffer { return @buffer; }
      >sub clear_buffer { @buffer = (); }
      >
      >
      >__END__
      >
      >
      >что называется, quick and dirty, но как пример сойдет


      • STDOUT/STDERR обработать через функцию, !*! andy, 11:20 , 05-Июл-07 (6)
        опять же не совсем понял. Некая функция должна перехватывать и обрабатывать строку непосредственно после её вывода? Ну тогда немного по другому сделаем:

        #!/usr/bin/perl
        use strict;
        use warnings;
        sub output_processor;

        tie *STDOUT, 'OUT', \&output_processor;
        #
        # лишний код для записи в файл писать неохота, у меня функция-обработчик
        # будет писать результат в STDERR
        #tie *STDERR, 'OUT', \&output_processor;

        print "qwe";
        warn "oops";
        print "asd";

        #untie *STDERR;
        untie *STDOUT;

        print "test line\n";

        sub output_processor {
          print STDERR "res: $_[0]\n";
        }

        #######################################################
        package OUT;
        our $processor_func;

        sub TIEHANDLE {
          ( my $self, $processor_func ) = @_;
          bless {}, $self;
        }
        sub UNTIE {}
        sub PRINT { $processor_func->( $_[1] ); }

        __END__

        если опять неправильно понял, то обозначьте задачу поточнее, поточнее будет и решение


        >Спасибо, andy!
        >Но не совсем полностью, что хотелось бы. В примере получается, что вывод будет осуществлен только после исполнения print_array( OUT->get_buffer ); Нужно другое - вывод срезу, после появления print или warn

        • STDOUT/STDERR обработать через функцию, !*! jr, 11:45 , 05-Июл-07 (7)
          Да, это то, что нужно, andy!
          Спасибо огромное, давно хотел узнать, как такое можно реализовать!

          Единственное, возник сразу же последующий вопрос.
          В данном примере STDOUT обрабатывается функцией output_processor и отравляется в STDERR. А как его (поток STDOUT) обработать и передать опять же в STDOUT, если так можно выразиться? Т.е. не перенаправлять STDOUT куда-то, а сделать что-то типа фильтра для него (фильтр в примере - это добавка "res: \n").

          >опять же не совсем понял. Некая функция должна перехватывать и обрабатывать строку
          >непосредственно после её вывода? Ну тогда немного по другому сделаем:
          >
          >#!/usr/bin/perl
          >use strict;
          >use warnings;
          >sub output_processor;
          >
          >tie *STDOUT, 'OUT', \&output_processor;
          >#
          ># лишний код для записи в файл писать неохота, у меня функция-обработчик
          >
          ># будет писать результат в STDERR
          >#tie *STDERR, 'OUT', \&output_processor;
          >
          >print "qwe";
          >warn "oops";
          >print "asd";
          >
          >#untie *STDERR;
          >untie *STDOUT;
          >
          >print "test line\n";
          >
          >sub output_processor {
          >  print STDERR "res: $_[0]\n";
          >}
          >
          >#######################################################
          >package OUT;
          >our $processor_func;
          >
          >sub TIEHANDLE {
          >  ( my $self, $processor_func ) = @_;
          >  bless {}, $self;
          >}
          >sub UNTIE {}
          >sub PRINT { $processor_func->( $_[1] ); }
          >
          >__END__
          >
          >если опять неправильно понял, то обозначьте задачу поточнее, поточнее будет и решение
          >
          >
          >

          • STDOUT/STDERR обработать через функцию, !*! andy, 11:57 , 05-Июл-07 (8)
            а вот это вопрос... Я такого никогда не делал. Т.е. в ранешних версиях перла можно было просто написать
            *REAL_STDOUT = STDOUT;
            tie *STDOUT, 'OUT'
            print REAL_STDOUT "Это неотфильтрованныя строка";

            сейчас такое не прокатывает. Мне сейчас некогда, я попозже примерчик напишу, ок? Заинтересовало.

            >Единственное, возник сразу же последующий вопрос.
            >В данном примере STDOUT обрабатывается функцией output_processor и отравляется в STDERR. А
            >как его (поток STDOUT) обработать и передать опять же в STDOUT,
            >если так можно выразиться? Т.е. не перенаправлять STDOUT куда-то, а сделать
            >что-то типа фильтра для него (фильтр в примере - это добавка
            >"res: \n").

          • STDOUT/STDERR обработать через функцию, !*! andy, 08:41 , 06-Июл-07 (9)
            по-быстрому получилось вот так, но почему-то мне этот код не нравится...
            "меня терзают смутные сомнения" (с)

            #!/usr/bin/perl
            use strict;
            use warnings;
            sub output_processor;

            tie *STDOUT, 'OUT', \&output_processor;

            print "qwe";
            warn "oops";
            print "asd";

            untie *STDOUT;

            print "test line\n";

            sub output_processor {
              my $obj = tied *STDOUT;
              untie *STDOUT;
              print "res: $_[0]\n";
              tie *STDOUT, $obj->get_name, \&{ (caller(0))[3] };
            }

            #######################################################
            package OUT;
            our( $classname, $processor_func );

            sub TIEHANDLE {
              ( $classname, $processor_func ) = @_;
              bless {};
            }
            sub UNTIE {}
            sub PRINT { $processor_func->( $_[1] );  }
            sub get_name { return $classname; }

            • STDOUT/STDERR обработать через функцию, !*! jr, 10:33 , 06-Июл-07 (10)
              Ок. Спасибо!

              >по-быстрому получилось вот так, но почему-то мне этот код не нравится...
              >"меня терзают смутные сомнения" (с)
              >
              >
              >
              >#!/usr/bin/perl
              >use strict;
              >use warnings;
              >sub output_processor;
              >
              >tie *STDOUT, 'OUT', \&output_processor;
              >
              >print "qwe";
              >warn "oops";
              >print "asd";
              >
              >untie *STDOUT;
              >
              >print "test line\n";
              >
              >sub output_processor {
              >  my $obj = tied *STDOUT;
              >  untie *STDOUT;
              >  print "res: $_[0]\n";
              >  tie *STDOUT, $obj->get_name, \&{ (caller(0))[3] };
              >}
              >
              >#######################################################
              >package OUT;
              >our( $classname, $processor_func );
              >
              >sub TIEHANDLE {
              >  ( $classname, $processor_func ) = @_;
              >  bless {};
              >}
              >sub UNTIE {}
              >sub PRINT { $processor_func->( $_[1] );  }
              >sub get_name { return $classname; }


            • STDOUT/STDERR обработать через функцию, !*! andy, 11:00 , 06-Июл-07 (11)
              что-то я действительно протупил. Как минимум имя класса, которому принадлежит объект, можно получить более правильно:

              sub output_processor {
                my $classname = ref( tied *STDOUT );
                untie *STDOUT;
                print "res: $_[0]\n";
                tie *STDOUT, $classname, \&{ (caller(0))[3] };
              }

              тогда в OUT дурацкий метод get_name и переменная пакета $classname становятся не нужны.

              • STDOUT/STDERR обработать через функцию, !*! jr, 11:34 , 06-Июл-07 (12)
                andy, спасибо огромное!
                я понял, как все это работает! :)

                >что-то я действительно протупил. Как минимум имя класса, которому принадлежит объект, можно
                >получить более правильно:
                >
                >sub output_processor {
                >  my $classname = ref( tied *STDOUT );
                >  untie *STDOUT;
                >  print "res: $_[0]\n";
                >  tie *STDOUT, $classname, \&{ (caller(0))[3] };
                >}
                >
                >тогда в OUT дурацкий метод get_name и переменная пакета $classname становятся не
                >нужны.


                • STDOUT/STDERR обработать через функцию, !*! NuINu, 12:31 , 06-Июл-07 (13)
                  >andy, спасибо огромное!
                  >я понял, как все это работает! :)

                  я думаю, тебе не безинтересно будет посмотреть на тот код что я сварганил:
                  пакет MyLoger.pm
                  -------------------------
                  package MyLoger;
                  require Tie::Handle;
                  #use Data::Dumper;

                  @ISA = qw(Tie::Handle);

                  sub PRINT {
                      my $self = shift;
                      if( defined($self->{'LOGS'}) ) {
                  #print "Printed tie\n";
                  my @tmp = @{$self->{'LOGS'}};
                  #print Dumper(@tmp)."\n";
                  foreach my $fh ( @tmp ) {
                       print  $fh @_;
                  }
                      }
                  }            # Provide a needed method


                  sub TIEHANDLE {
                      my $class = shift;
                      my $self= {};
                      my $fh;
                      my @handles;
                      if(@_ >= 0) {
                  foreach my $namelog (@_) {
                       open($fh, $namelog);
                       push @handles, $fh;
                       undef $fh;
                  }
                      }
                      $self->{'LOGS'} = \@handles;
                      bless $self,$class;
                      return $self;
                  }       # Overrides inherited method

                  sub UNTIE {
                      my $self = shift;
                      if( defined($self->{'LOGS'}) ) {
                  foreach my $fh (@{$self->{'LOGS'}}) {
                       close ($fh);
                  }
                      }
                  }            # Provide a needed method

                  1;
                  -------------------------

                  и тестовая программка :
                  #!/usr/bin/perl -w

                  use strict;
                  use MyLoger;
                  use Data::Dumper;


                  print "test1\n";
                  print "test2\n";
                  print "test3\n";
                  print "test4\n";

                  my $tie_logs = tie *STDOUT, 'MyLoger', ">&STDOUT",'>tie1.log', '>>tie2.log';
                  #print Dumper($tie_logs)."\n";

                  print "test11\n";
                  print "test21\n";
                  print "test31\n";
                  print "test41\n";

                  untie *STDOUT;

                  • STDOUT/STDERR обработать через функцию, !*! jr, 12:58 , 06-Июл-07 (14)
                    да, не безинтересно! :)
                    я не знал до этого времени tie/untie функцию и с классами особо не работал
                    спасибо!

                    >я думаю, тебе не безинтересно будет посмотреть на тот код что я
                    >сварганил:
                    >пакет MyLoger.pm
                    >-------------------------
                    >package MyLoger;
                    >require Tie::Handle;
                    >#use Data::Dumper;
                    >
                    >@ISA = qw(Tie::Handle);
                    >
                    >sub PRINT {
                    >    my $self = shift;
                    >    if( defined($self->{'LOGS'}) ) {
                    > #print "Printed tie\n";
                    > my @tmp = @{$self->{'LOGS'}};
                    > #print Dumper(@tmp)."\n";
                    > foreach my $fh ( @tmp ) {
                    >     print  $fh @_;
                    > }
                    >    }
                    >}            
                    ># Provide a needed method
                    >
                    >
                    >sub TIEHANDLE {
                    >    my $class = shift;
                    >    my $self= {};
                    >    my $fh;
                    >    my @handles;
                    >    if(@_ >= 0) {
                    > foreach my $namelog (@_) {
                    >     open($fh, $namelog);
                    >     push @handles, $fh;
                    >     undef $fh;
                    > }
                    >    }
                    >    $self->{'LOGS'} = \@handles;
                    >    bless $self,$class;
                    >    return $self;
                    >}       # Overrides inherited method
                    >
                    >sub UNTIE {
                    >    my $self = shift;
                    >    if( defined($self->{'LOGS'}) ) {
                    > foreach my $fh (@{$self->{'LOGS'}}) {
                    >     close ($fh);
                    > }
                    >    }
                    >}            
                    ># Provide a needed method
                    >
                    >1;
                    >-------------------------
                    >
                    >и тестовая программка :
                    >#!/usr/bin/perl -w
                    >
                    >use strict;
                    >use MyLoger;
                    >use Data::Dumper;
                    >
                    >
                    >print "test1\n";
                    >print "test2\n";
                    >print "test3\n";
                    >print "test4\n";
                    >
                    >my $tie_logs = tie *STDOUT, 'MyLoger', ">&STDOUT",'>tie1.log', '>>tie2.log';
                    >#print Dumper($tie_logs)."\n";
                    >
                    >print "test11\n";
                    >print "test21\n";
                    >print "test31\n";
                    >print "test41\n";
                    >
                    >untie *STDOUT;


  • STDOUT/STDERR обработать через функцию, !*! NuINu, 10:00 , 05-Июл-07 (4)
    >Есть скрипт perl, который что-то выводит в STDOUT и в STDERR через
    >print. Нужно не меняя print обработать этот вывод через функцию и
    >перенаправить его куда-нибудь в другое место.
    >Как это сделать?


    open(LOG, '>>', $month_logsfile) or die "Can't open log file $month_logsfile\n";
    open(STDOUT, ">>&LOG");
    open(STDERR, ">>&LOG");

    • STDOUT/STDERR обработать через функцию, !*! jr, 10:18 , 05-Июл-07 (5)
      Нет, это не совсем то. Мне не нужно просто перенаправить вывод в файл. Мне нужно обработать вывод некоторой функцией и уже потом его перенаправить куда-нибудь.

      >
      >open(LOG, '>>', $month_logsfile) or die "Can't open log file $month_logsfile\n";
      >open(STDOUT, ">>&LOG");
      >open(STDERR, ">>&LOG");





Партнёры:
PostgresPro
Inferno Solutions
Hosting by Hoster.ru
Хостинг:

Закладки на сайте
Проследить за страницей
Created 1996-2025 by Maxim Chirkov
Добавить, Поддержать, Вебмастеру