See reply below, please


>
> I happen to be scripting something that needs to have two logs written
> to and was sort of taken by how awkward this construction looked:
>
> (Simplified for discussion, from a longer script)
>
>   my $rsync = 'rsync';
>   my $tmplog = 'one.log';
>   my $tmplog2 = 'two.log';
>   open(LOG,">>$tmplog")or die "Can't open $tmplog : $!";
>   open(LOG2,">>$tmplog2")or die "Can't open $tmplog2: $!";
>   print LOG  "kdkdkdkd Output from:\n$rsync cmdflgs";
>   print LOG2 "kdkdkdkd Output from:\n$rsync cmdflgs"
>   close(LOG);
>   close(LOG2);
>
> Is there some smooth way to write to more than one log?
>
> I tried just adding the second one to the first print like this:
>
>  print LOG LOG2 "[...]";
>
>   But that fails with an error:
>
>   String found where operator expected at ./t1.pl line 109, near "LOG2
>   "kdkdkdkd Output from:\n$rsync cmdflgs""
>
>         (Do you need to predeclare LOG2?)
>
>   syntax error at ./t1.pl line 109, near "LOG2 "kdkdkdkd Output
>   from:\n$rsync cmdflgs""
>
>   Execution of ./t1.pl aborted due to compilation errors.
>
>
> --
> To unsubscribe, e-mail: beginners-unsubscr...@perl.org
> For additional commands, e-mail: beginners-h...@perl.org
> http://learn.perl.org/
>
>
>
>

Harry,

In my quest to always attack small rodents with bazookas, I came up
with a solution that involves OO.  It is a small class file.  Yes, to
all of the OO lovers out there, I *know* that it is not 100% ready for
prime time...  it is simply a small example for Harry (or any other
interested party) to see.  Before using it in production, the error
checking needs to be fleshed out/changed, etc., etc.  But, flame away
if you feel the need.

Anyway..  using this little class (I named Multiprint), your code
would look something like this:

  use Multiprint;

  my $rsync = "rsync";

  my $tmplog = 'one.log';
  my $tmplog2 = 'two.log';

  my $mp = Multiprint->new();

  $mp->open("LOG", ">>", "$tmplog");
  $mp->open("LOG2", ">>", "$tmplog2");

  $mp->print("kdkdkdkd Output from:\n$rsync cmdflgs");

The opens are not 100% necessary..  the class will accept file
specifications in the call to new() also.  I omitted the close calls,
also, because the module takes care of it for you, but there is a
close() method provided. Please see the code for the module below for
more information.

Best of luck, Harry

Nathan


Multiprint.pm:


package Multiprint;

#
#  Multiprint:  Less ugly printing to multiple file handles
#

# ["name", "mode", "filename"]

#
#  new: create a new Multiprint instance.  May optionally except one
or more ARRAY REFS as
#  arguments.  If provided, the array refs must refer to three element
arrays. The first
#  element is an internal name that is used to access the filehandle,
the second element
#  is a mode (and must be either ">" or ">>", for overwrite and append
respectively), and
#  the third element is the path name of the file to open.  Returns a
blessed reference to
#  a Multiprint object.
#

  sub new {
    my $class = shift;
    my $self = {};
    bless $self, $class;
    $self->{FILES} = {};
    foreach my $filespecref (@_) {
      $self->open(@$filespecref ) if ref($filespecref) eq 'ARRAY';
    }
    return $self;
  }

#
#  open: Opens a file for output.  Requires three arguments; an
internal name, a mode, and
#  a file path name.  See "new()" for more information.
#

  sub open {
    my ($self, $name, $mode, $fname) = @_;

    if (! defined $name or
        ! defined $fname or
        ! defined $mode or
        $mode !~ /\>{1,2}/ ) {
      die "Error: arguments to open() were invalid"
    }

    open my $fh, "$mode", "$fname" or
      die "Error opening file $fname: $!";

    $self->{FILES}{$name} = [$fh, $fname];
    return $fh;
  }

#
#  print:  Accepts one or more arguments.  The arguments are printed
to all of the open files,
#  in ASCIIbetical order.
#

  sub print {
    my $self = shift;
    foreach my $fileentry (sort keys %{$self->{FILES}}) {
      my $fh = $self->{FILES}{$fileentry}[0];
      print {$fh} @_;
    }

    return 1;

  }

#
#  close:  Closes a file.  Requires one parameter, the internal name
of the file to close.
#  not technically necessary, because all files would be automatically
closed when the
#  file handle reference is garbage collected, but is nice to have
anyway.  This sub
#  is also used by the DESTROY method to close all files explicitly
when the object instance is
#  destroyed
#

  sub close {
    my $self  = shift;
    my $name = shift;
    close $self->{FILES}{$name}[0] if exists $self->{FILES}{$name};
    return 1;
  }


#
#  DESTROY: Called automagically when an instance of Multiprint has no
more active references.
#  Simply closes each file.
#

  sub DESTROY {
    my $self = shift;
    foreach my $name (sort keys %{$self->{FILES}}) {
      $self->close($name);
    }
  }



  1;



-- 



-- 
To unsubscribe, e-mail: beginners-unsubscr...@perl.org
For additional commands, e-mail: beginners-h...@perl.org
http://learn.perl.org/


Reply via email to