[30297] in Perl-Users-Digest

home help back first fref pref prev next nref lref last post

Perl-Users Digest, Issue: 1540 Volume: 11

daemon@ATHENA.MIT.EDU (Perl-Users Digest)
Tue May 13 14:09:47 2008

Date: Tue, 13 May 2008 11:09:14 -0700 (PDT)
From: Perl-Users Digest <Perl-Users-Request@ruby.OCE.ORST.EDU>
To: Perl-Users@ruby.OCE.ORST.EDU (Perl-Users Digest)

Perl-Users Digest           Tue, 13 May 2008     Volume: 11 Number: 1540

Today's topics:
        A little Direction Please <Ramroop@gmail.com>
    Re: A little Direction Please <ben@morrow.me.uk>
    Re: A little Direction Please <jurgenex@hotmail.com>
    Re: A little Direction Please <RedGrittyBrick@SpamWeary.foo>
    Re: A little Direction Please <Ramroop@gmail.com>
    Re: A little Direction Please <jurgenex@hotmail.com>
    Re: Constants across package boundaries <ThomasKratz@REMOVEwebCAPS.de>
    Re: Constants across package boundaries <1usa@llenroc.ude.invalid>
    Re: Constants across package boundaries <ben@morrow.me.uk>
    Re: Constants across package boundaries <ThomasKratz@REMOVEwebCAPS.de>
    Re: Constants across package boundaries <1usa@llenroc.ude.invalid>
    Re: Constants across package boundaries <ThomasKratz@REMOVEwebCAPS.de>
    Re: Constants across package boundaries <bernie@fantasyfarm.com>
    Re: Constants across package boundaries <bernie@fantasyfarm.com>
    Re: Constants across package boundaries <ben@morrow.me.uk>
    Re: How to pass around an Array of Arrays (or Array Ref <1usa@llenroc.ude.invalid>
    Re: How to pass around an Array of Arrays (or Array Ref <jurgenex@hotmail.com>
        Digest Administrivia (Last modified: 6 Apr 01) (Perl-Users-Digest Admin)

----------------------------------------------------------------------

Date: Tue, 13 May 2008 08:25:00 -0700 (PDT)
From: Andy <Ramroop@gmail.com>
Subject: A little Direction Please
Message-Id: <f6703988-3a51-4991-a4c5-d2ff0e92cd6e@c65g2000hsa.googlegroups.com>

Greets :)


Q; I am trying to learn how to define some variables

The basis of this script is to Scrub log files for ftp logins,
seperate the successful logins

Then create an array ( I hope the right terminology) to seperate it

I hardcoded the log file, because I am looking for a way for it to
scrub *.logs on a server

but ...hey step by step right.

Fields: date time c-ip cs-username cs-method cs-uri-stem sc-status sc-
bytes cs-host
           2008-01-20 00:00:02 x.x.x.x 0598_Andy [6952041]sent /
0598_Andy/qff0598.zip 226 0 -

This field 226 0 - is a successful login

My plan is to scrub the logs, export to file.

sort fields into variable.

I hope in the end to get

1..log of successful logins
2.log of last successful login ( I think I am going to try date
comparison from most recent to last.)
3 be able to parse the fields and get data.


I know that there are those of you who are advanced, I would
appreciate any directions or help.

Again I am trying to put this together this is what  I have so far.

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

open(INPUT, '<', "ex080120.log")or die("Could not open log file.");
open(OUTPUT, '>',"ftpacct.log")or die("Could not open log file.");
my $extractedLine;
while (<INPUT>) {
 my $line = $_;
         if ($line =~ m/^(.+226\s+0\s+-\s+.*)$/) {
              print OUTPUT "$1\n";
         }
}
close(INPUT);
close(OUTPUT);
exit;



------------------------------

Date: Tue, 13 May 2008 16:56:27 +0100
From: Ben Morrow <ben@morrow.me.uk>
Subject: Re: A little Direction Please
Message-Id: <baqof5-ko21.ln1@osiris.mauzo.dyndns.org>


Quoth Andy <Ramroop@gmail.com>:
> Greets :)
> 
> Q; I am trying to learn how to define some variables
> 
> The basis of this script is to Scrub log files for ftp logins,
> seperate the successful logins
> 
> Then create an array ( I hope the right terminology) to seperate it
> 
> I hardcoded the log file, because I am looking for a way for it to
> scrub *.logs on a server
> 
> but ...hey step by step right.
> 
> Fields: date time c-ip cs-username cs-method cs-uri-stem sc-status sc-
> bytes cs-host
>            2008-01-20 00:00:02 x.x.x.x 0598_Andy [6952041]sent /
> 0598_Andy/qff0598.zip 226 0 -

What are these fields separated by? A single space? Can the fields ever
contain spaces? How are they quoted in that case? What about newlines?

> This field 226 0 - is a successful login
> 
> My plan is to scrub the logs, export to file.
> 
> sort fields into variable.
> 
> I hope in the end to get
> 
> 1..log of successful logins
> 2.log of last successful login ( I think I am going to try date
> comparison from most recent to last.)
> 3 be able to parse the fields and get data.
> 
> 
> I know that there are those of you who are advanced, I would
> appreciate any directions or help.
> 
> Again I am trying to put this together this is what  I have so far.
> 
> #!/usr/bin/perl
> use strict;
> use warnings;
> 
> open(INPUT, '<', "ex080120.log")or die("Could not open log file.");
> open(OUTPUT, '>',"ftpacct.log")or die("Could not open log file.");

3-arg open: good.
Checking the return value: good.
It's better to keep filehandles in variables than use the old-fashioned
global handles, though; and if the open fails you should say what
failed, and why:

    open(my $INPUT, '<', "ex080120.log") 
        or die("can't read ex080120.log: $!");
    open(my $OUTPUT, '>', "ftpacct.log") 
        or die("can't write ftpacct.log: $!);

> my $extractedLine;
> while (<INPUT>) {
>  my $line = $_;

This is silly. If you want the line in $line, put it there in the first
place:

    while (my $line = <$INPUT>) {

>          if ($line =~ m/^(.+226\s+0\s+-\s+.*)$/) {
>               print OUTPUT "$1\n";
>          }

I would recommend splitting the line into a hash first, and then
selecting lines based on that. Something like

    my @fields = qw/
        date time c_ip 
        cs_username cs_method cs_uri_stem 
        sc_status sc_bytes cs_host
    /;

    while (my $line = <$INPUT>) {

        # Here I assume fields are delimited by a single space, and
        # spaces and newlines *never* appear in a field (not even inside
        # quotes). If this isn't true, you probably want to use the
        # Text::CSV_XS module, which can parse all sorts of
        # <foo>-delimited files.

        my %record;
        @record{@fields} = split / /, $line;

        $record{sc_status} == 226 
            and $record{sc_bytes} == 0
            and $record{cs_host} eq '-'
            or next;

        print $OUTPUT $line;
    }

Once you've understood that bit of code it should be straightforward to
change it to do something more sophisticated. To keep track of the last
login for any given user, you need a hash %lastlogin, keyed by username,
that lives outside the loop.

> }
> close(INPUT);
> close(OUTPUT);

An advantage of keeping filehandles in variables is that they are closed
for you when the variable goes out of scope. An advantage of real
operating systems (Win32 counts, here) is that they close filehandles
for you when the process exits, in any case.

That said, there is value in explicitly closing a filehandle opened for
writing, *and checking the return value*. If any of the writes to that
filehandle failed (disk full, for instance) the error will be returned
by close. (Of course, if you want to catch errors sooner than that, you
can check the return value of print instead.)

> exit;

There's no need to explicitly exit from a Perl program. Falling off the
end is the usual way to finish.

Ben

-- 
I've seen things you people wouldn't believe: attack ships on fire off
the shoulder of Orion; I watched C-beams glitter in the dark near the
Tannhauser Gate. All these moments will be lost, in time, like tears in rain.
Time to die.                                                   ben@morrow.me.uk


------------------------------

Date: Tue, 13 May 2008 16:21:08 GMT
From: Jürgen Exner <jurgenex@hotmail.com>
Subject: Re: A little Direction Please
Message-Id: <okfj24lqpn132ataa7293da0omddn6jpo5@4ax.com>

Andy <Ramroop@gmail.com> wrote:
>Q; I am trying to learn how to define some variables

To define a variable in Perl typically you use the assignment operator
'='.

>The basis of this script is to Scrub log files for ftp logins,
>seperate the successful logins
>
>Then create an array ( I hope the right terminology) to seperate it
>
>I hardcoded the log file, because I am looking for a way for it to
>scrub *.logs on a server
>
>but ...hey step by step right.
>
>Fields: date time c-ip cs-username cs-method cs-uri-stem sc-status sc-
>bytes cs-host
>           2008-01-20 00:00:02 x.x.x.x 0598_Andy [6952041]sent /
>0598_Andy/qff0598.zip 226 0 -
>
>This field 226 0 - is a successful login
>
>My plan is to scrub the logs, export to file.
>
>sort fields into variable.
>
>I hope in the end to get
>
>1..log of successful logins
>2.log of last successful login ( I think I am going to try date
>comparison from most recent to last.)
>3 be able to parse the fields and get data.
>
>
>I know that there are those of you who are advanced, I would
>appreciate any directions or help.
>
>Again I am trying to put this together this is what  I have so far.
>
>#!/usr/bin/perl
>use strict;
>use warnings;
>
>open(INPUT, '<', "ex080120.log")or die("Could not open log file.");
>open(OUTPUT, '>',"ftpacct.log")or die("Could not open log file.");

You might want to add the reason why the open() call failed and the file
name for which it failed.

>my $extractedLine;

Why declare a variable that you never use again?

>while (<INPUT>) {
> my $line = $_;
>         if ($line =~ m/^(.+226\s+0\s+-\s+.*)$/) {

I know for some people it is difficult to just trust the default
argument. But I would write this as 
	while (<INPUT>) {
		if (m/^(.+226\s+0\s+-\s+.*)$/) {
or
	while (my $line=<INPUT>) {
		if ($line =~ m/^(.+226\s+0\s+-\s+.*)$/) {

>              print OUTPUT "$1\n";
>         }
>}
>close(INPUT);
>close(OUTPUT);

You may want to check the success of the close() call, too, in
particular for a file handle you wrote to.

jue


------------------------------

Date: Tue, 13 May 2008 17:35:59 +0100
From: RedGrittyBrick <RedGrittyBrick@SpamWeary.foo>
Subject: Re: A little Direction Please
Message-Id: <4829c371$0$2487$da0feed9@news.zen.co.uk>

Andy wrote:
> Greets :)
> 
> 
> Q; I am trying to learn how to define some variables
> 
> The basis of this script is to Scrub log files for ftp logins,
> seperate the successful logins
> 
> Then create an array ( I hope the right terminology) to seperate it
> 
> I hardcoded the log file, because I am looking for a way for it to
> scrub *.logs on a server
> 
> but ...hey step by step right.
> 
> Fields: date time c-ip cs-username cs-method cs-uri-stem sc-status sc-
> bytes cs-host
>            2008-01-20 00:00:02 x.x.x.x 0598_Andy [6952041]sent /
> 0598_Andy/qff0598.zip 226 0 -
> 
> This field 226 0 - is a successful login
> 
> My plan is to scrub the logs, export to file.
> 
> sort fields into variable.

perldoc -f split


> 
> I hope in the end to get
> 
> 1..log of successful logins

grep "226 0 - *$" ex*.log > ftpacct.log

perl -n -e 'print if /226 0 - *$/' ex*.log > ftpacct.log

> 2.log of last successful login ( I think I am going to try date
> comparison from most recent to last.)

Logfiles are generally in date order, you just need the last record.

tail -n 1 successful-logins.log > last-successful-login.log

> 3 be able to parse the fields and get data.
> 
> 
> I know that there are those of you who are advanced, I would
> appreciate any directions or help.
> 
> Again I am trying to put this together this is what  I have so far.
> 
> #!/usr/bin/perl
> use strict;
> use warnings;

Good!

> 
> open(INPUT, '<', "ex080120.log")or die("Could not open log file.");

Best practise is to ...
- Use lexical filehandles
- Include filename in message
- Include the failure reason in the message

my $filename = 'ex080120.log';
open(my $input, '<', $filename)
   or die("Could not open '$filename' because $!");

> open(OUTPUT, '>',"ftpacct.log")or die("Could not open log file.");

see above

> my $extractedLine;

Not used? Remove it.

> while (<INPUT>) {
>  my $line = $_;

It's sometimes easier to work with $_ than assign it to another 
variable. It would simplify your later code.

>          if ($line =~ m/^(.+226\s+0\s+-\s+.*)$/) {

Matching ^.+ is wasteful.
You don't need to capture the whole line using ().

>               print OUTPUT "$1\n";

Unless you chomp your input you'll output an extra blank line.

Putting all the above together

           if (/226\s+0\s+-\s*$/) {
                 print OUTPUT;

OR

           print OUTPUT if /\s+0\s+-\s*$/;

Though I'd use lexical filehandles, as I wrote earlier.

           print $output if /\s+0\s+-\s*$/;

However to achieve your other aim, use your original construction and add
           $last_login = $line;
           my ($date, $time, ... $hyphen) = split;
           ...


>          }
> }
> close(INPUT);
> close(OUTPUT);

print "last successful login is $last_login";

> exit;
> 


Untested, caveat emptor.

-- 
RGB


------------------------------

Date: Tue, 13 May 2008 10:19:50 -0700 (PDT)
From: Andy <Ramroop@gmail.com>
Subject: Re: A little Direction Please
Message-Id: <33810dbd-1865-454d-99e5-e92e7adf0703@56g2000hsm.googlegroups.com>

On May 13, 12:35 pm, RedGrittyBrick <RedGrittyBr...@SpamWeary.foo>
wrote:
> Andy wrote:
> > Greets :)
>
> > Q; I am trying to learn how to define some variables
>
> > The basis of this script is to Scrub log files for ftp logins,
> > seperate the successful logins
>
> > Then create an array ( I hope the right terminology) to seperate it
>
> > I hardcoded the log file, because I am looking for a way for it to
> > scrub *.logs on a server
>
> > but ...hey step by step right.
>
> > Fields: date time c-ip cs-username cs-method cs-uri-stem sc-status sc-
> > bytes cs-host
> >            2008-01-20 00:00:02 x.x.x.x 0598_Andy [6952041]sent /
> > 0598_Andy/qff0598.zip 226 0 -
>
> > This field 226 0 - is a successful login
>
> > My plan is to scrub the logs, export to file.
>
> > sort fields into variable.
>
> perldoc -f split
>
>
>
> > I hope in the end to get
>
> > 1..log of successful logins
>
> grep "226 0 - *$" ex*.log > ftpacct.log
>
> perl -n -e 'print if /226 0 - *$/' ex*.log > ftpacct.log
>
> > 2.log of last successful login ( I think I am going to try date
> > comparison from most recent to last.)
>
> Logfiles are generally in date order, you just need the last record.
>
> tail -n 1 successful-logins.log > last-successful-login.log
>
> > 3 be able to parse the fields and get data.
>
> > I know that there are those of you who are advanced, I would
> > appreciate any directions or help.
>
> > Again I am trying to put this together this is what  I have so far.
>
> > #!/usr/bin/perl
> > use strict;
> > use warnings;
>
> Good!
>
>
>
> > open(INPUT, '<', "ex080120.log")or die("Could not open log file.");
>
> Best practise is to ...
> - Use lexical filehandles
> - Include filename in message
> - Include the failure reason in the message
>
> my $filename = 'ex080120.log';
> open(my $input, '<', $filename)
>    or die("Could not open '$filename' because $!");
>
> > open(OUTPUT, '>',"ftpacct.log")or die("Could not open log file.");
>
> see above
>
> > my $extractedLine;
>
> Not used? Remove it.
>
> > while (<INPUT>) {
> >  my $line = $_;
>
> It's sometimes easier to work with $_ than assign it to another
> variable. It would simplify your later code.
>
> >          if ($line =~ m/^(.+226\s+0\s+-\s+.*)$/) {
>
> Matching ^.+ is wasteful.
> You don't need to capture the whole line using ().
>
> >               print OUTPUT "$1\n";
>
> Unless you chomp your input you'll output an extra blank line.
>
> Putting all the above together
>
>            if (/226\s+0\s+-\s*$/) {
>                  print OUTPUT;
>
> OR
>
>            print OUTPUT if /\s+0\s+-\s*$/;
>
> Though I'd use lexical filehandles, as I wrote earlier.
>
>            print $output if /\s+0\s+-\s*$/;
>
> However to achieve your other aim, use your original construction and add
>            $last_login = $line;
>            my ($date, $time, ... $hyphen) = split;
>            ...
>
> >          }
> > }
> > close(INPUT);
> > close(OUTPUT);
>
> print "last successful login is $last_login";
>
> > exit;
>
> Untested, caveat emptor.
>
> --
> RGB

WOW!

Guys you opened my eyes up...I knew there were many ways to do this ,
it is just confusing figuring out which one to use.
I have of course google'd for file manipulations and sorting , I guess
it just takes experience to figure out which is best.

Thanks for the responses, all I have to do is figure out how to take
what you have advised me and try to get it to work.

I think I can safely say " progress in motion".....umm slowly. :)

I will try your suggestions and see what happens.....

-Thank you again

GREATLY APPRECIATED :)






------------------------------

Date: Tue, 13 May 2008 17:20:47 GMT
From: Jürgen Exner <jurgenex@hotmail.com>
Subject: Re: A little Direction Please
Message-Id: <2bjj249e77fe9m2fqhgf89ugl3c1j3p7eh@4ax.com>

RedGrittyBrick <RedGrittyBrick@SpamWeary.foo> wrote:
>Andy wrote:
>>          if ($line =~ m/^(.+226\s+0\s+-\s+.*)$/) {
>
>Matching ^.+ is wasteful.
>You don't need to capture the whole line using ().
>
>>               print OUTPUT "$1\n";
>
>Unless you chomp your input you'll output an extra blank line.

My first thought, too. However because of the rather 'interesting' way
he is printing the captured group instead of just the plain line he is
loosing the newline in the pattern match. Therefore he has to add it
back explicitely.

>           print OUTPUT if /\s+0\s+-\s*$/;

Much nicer, of course.

jue


------------------------------

Date: Tue, 13 May 2008 17:09:04 +0200
From: Thomas Kratz <ThomasKratz@REMOVEwebCAPS.de>
Subject: Re: Constants across package boundaries
Message-Id: <4829af10$0$2647$bb690d87@news.main-rheiner.de>

A. Sinan Unur wrote:

> package My::Constants;
> 
> use strict;
> use warnings;
> 
> use base qw( Exporter );
> 
> our @EXPORT = qw();
> our @EXPORT_OK = qw( ONE TWO THREE );
> 
> use constant ONE => 'one';
> use constant TWO => 'two';
> use constant THREE => 'three';
> 
> 1;

I just needed that last week for a module but found the:

  our @EXPORT_OK = qw( ONE TWO THREE );

a bit tedious when you are having many constants. I had to play around a 
bit and found you can do (maybe that's obvious, but it wasn't to me):

  my %constant_hash;
  BEGIN {
    %constant_hash = (
      ONE   => 'one',
      TWO   => 'two',
      THREE => 'three',
    };
  }
  our @EXPORT_OK   = keys %constant_hash;
  our %EXPORT_TAGS = (
     constants => [keys %constant_hash],
  );

Thomas

-- 
$/=$,,$_=<DATA>,s,(.*),$1,see;__END__
s,^(.*\043),,mg,@_=map{[split'']}split;{#>J~.>_an~>>e~......>r~
$_=$_[$%][$"];y,<~>^,-++-,?{$/=--$|?'"':#..u.t.^.o.P.r.>ha~.e..
'%',s,(.),\$$/$1=1,,$;=$_}:/\w/?{y,_, ,,#..>s^~ht<._..._..c....
print}:y,.,,||last,,,,,,$_=$;;eval,redo}#.....>.e.r^.>l^..>k^.-


------------------------------

Date: Tue, 13 May 2008 15:27:52 GMT
From: "A. Sinan Unur" <1usa@llenroc.ude.invalid>
Subject: Re: Constants across package boundaries
Message-Id: <Xns9A9D749E74356asu1cornelledu@127.0.0.1>

Thomas Kratz <ThomasKratz@REMOVEwebCAPS.de> wrote in
news:4829af10$0$2647$bb690d87@news.main-rheiner.de: 

> A. Sinan Unur wrote:
> 
>> package My::Constants;
>> 
>> use strict;
>> use warnings;
>> 
>> use base qw( Exporter );
>> 
>> our @EXPORT = qw();
>> our @EXPORT_OK = qw( ONE TWO THREE );
>> 
>> use constant ONE => 'one';
>> use constant TWO => 'two';
>> use constant THREE => 'three';
>> 
>> 1;
> 
> I just needed that last week for a module but found the:
> 
>   our @EXPORT_OK = qw( ONE TWO THREE );
> 
> a bit tedious when you are having many constants. I had to play around
> a bit and found you can do (maybe that's obvious, but it wasn't to
> me): 
> 
>   my %constant_hash;
>   BEGIN {
>     %constant_hash = (
>       ONE   => 'one',
>       TWO   => 'two',
>       THREE => 'three',
>     };

Ooops, s/}/)/ ;-)

>   }
>   our @EXPORT_OK   = keys %constant_hash;
>   our %EXPORT_TAGS = (
>      constants => [keys %constant_hash],
>   );

To avoid having to type the use constant statements as well, you need 
something along the lines of

BEGIN {

# see above for %constant_hash

    for my $k ( keys %constant_hash ) {
        no strict 'refs';
        *{ "My::Constants::$k" } = sub {  $constant_hash{ $k } };
    }
};


Sinan

-- 
A. Sinan Unur <1usa@llenroc.ude.invalid>
(remove .invalid and reverse each component for email address)

comp.lang.perl.misc guidelines on the WWW:
http://www.rehabitation.com/clpmisc/


------------------------------

Date: Tue, 13 May 2008 16:27:14 +0100
From: Ben Morrow <ben@morrow.me.uk>
Subject: Re: Constants across package boundaries
Message-Id: <ijoof5-of11.ln1@osiris.mauzo.dyndns.org>


Quoth Thomas Kratz <ThomasKratz@REMOVEwebCAPS.de>:
> A. Sinan Unur wrote:
> 
> > package My::Constants;
> > 
> > use strict;
> > use warnings;
> > 
> > use base qw( Exporter );
> > 
> > our @EXPORT = qw();
> > our @EXPORT_OK = qw( ONE TWO THREE );
> > 
> > use constant ONE => 'one';
> > use constant TWO => 'two';
> > use constant THREE => 'three';
> > 
> > 1;
> 
> I just needed that last week for a module but found the:
> 
>   our @EXPORT_OK = qw( ONE TWO THREE );
> 
> a bit tedious when you are having many constants. I had to play around a 
> bit and found you can do (maybe that's obvious, but it wasn't to me):
> 
>   my %constant_hash;
>   BEGIN {
>     %constant_hash = (
>       ONE   => 'one',
>       TWO   => 'two',
>       THREE => 'three',
>     };
>   }
>   our @EXPORT_OK   = keys %constant_hash;
>   our %EXPORT_TAGS = (
>      constants => [keys %constant_hash],
>   );

There's no need for the BEGIN block: since this is a 'use'd module,
everything will happen at BEGIN time anyway.

    require constant;

    my %constants = (
        ONE => 'one',
        TWO => 'two',
    );

    our (@EXPORT_OK, %EXPORT_TAGS);

    for (keys %constants) {
        constant->import($_ => $constants{$_});
        push @{ %EXPORT_TAGS{constants} }, $_;
    }
    push @EXPORT_OK, @{ %EXPORT_TAGS{constants} };

Ben

-- 
"Faith has you at a disadvantage, Buffy."
"'Cause I'm not crazy, or 'cause I don't kill people?"
"Both, actually."
                                                         [ben@morrow.me.uk]


------------------------------

Date: Tue, 13 May 2008 17:39:34 +0200
From: Thomas Kratz <ThomasKratz@REMOVEwebCAPS.de>
Subject: Re: Constants across package boundaries
Message-Id: <4829b636$0$2672$bb690d87@news.main-rheiner.de>

A. Sinan Unur wrote:
> Thomas Kratz <ThomasKratz@REMOVEwebCAPS.de> wrote in
> news:4829af10$0$2647$bb690d87@news.main-rheiner.de: 
> 
>> A. Sinan Unur wrote:
>>
>>> package My::Constants;
>>>
>>> use strict;
>>> use warnings;
>>>
>>> use base qw( Exporter );
>>>
>>> our @EXPORT = qw();
>>> our @EXPORT_OK = qw( ONE TWO THREE );
>>>
>>> use constant ONE => 'one';
>>> use constant TWO => 'two';
>>> use constant THREE => 'three';
>>>
>>> 1;
>> I just needed that last week for a module but found the:
>>
>>   our @EXPORT_OK = qw( ONE TWO THREE );
>>
>> a bit tedious when you are having many constants. I had to play around
>> a bit and found you can do (maybe that's obvious, but it wasn't to
>> me): 
>>
>>   my %constant_hash;
>>   BEGIN {
>>     %constant_hash = (
>>       ONE   => 'one',
>>       TWO   => 'two',
>>       THREE => 'three',
>>     };
> 
> Ooops, s/}/)/ ;-)

I really should use a bigger font in my newsreader :-)

> 
>>   }
>>   our @EXPORT_OK   = keys %constant_hash;
>>   our %EXPORT_TAGS = (
>>      constants => [keys %constant_hash],
>>   );
> 
> To avoid having to type the use constant statements as well, you need 
> something along the lines of
> 
> BEGIN {
> 
> # see above for %constant_hash
> 
>     for my $k ( keys %constant_hash ) {
>         no strict 'refs';
>         *{ "My::Constants::$k" } = sub {  $constant_hash{ $k } };
>     }
> };

Ah No! I forgot the most important line in my post :-(
You can simply do a:

  use constant \%constant_hash;

right after the BEGIN block. That was the reason for creating the hash 
in the first place. I should have run the code after extracting it from 
the module.

Thomas

-- 
$/=$,,$_=<DATA>,s,(.*),$1,see;__END__
s,^(.*\043),,mg,@_=map{[split'']}split;{#>J~.>_an~>>e~......>r~
$_=$_[$%][$"];y,<~>^,-++-,?{$/=--$|?'"':#..u.t.^.o.P.r.>ha~.e..
'%',s,(.),\$$/$1=1,,$;=$_}:/\w/?{y,_, ,,#..>s^~ht<._..._..c....
print}:y,.,,||last,,,,,,$_=$;;eval,redo}#.....>.e.r^.>l^..>k^.-


------------------------------

Date: Tue, 13 May 2008 15:43:59 GMT
From: "A. Sinan Unur" <1usa@llenroc.ude.invalid>
Subject: Re: Constants across package boundaries
Message-Id: <Xns9A9D775995779asu1cornelledu@127.0.0.1>

Thomas Kratz <ThomasKratz@REMOVEwebCAPS.de> wrote in news:4829b636$0$2672
$bb690d87@news.main-rheiner.de:

> You can simply do a:
> 
>   use constant \%constant_hash;
> 
> right after the BEGIN block.

Makes perfect sense now that I see it but I must admit it would have never 
occurred to me to do that. Thanks for pointing it out.

Sinan
-- 
A. Sinan Unur <1usa@llenroc.ude.invalid>
(remove .invalid and reverse each component for email address)

comp.lang.perl.misc guidelines on the WWW:
http://www.rehabitation.com/clpmisc/


------------------------------

Date: Tue, 13 May 2008 17:46:51 +0200
From: Thomas Kratz <ThomasKratz@REMOVEwebCAPS.de>
Subject: Re: Constants across package boundaries
Message-Id: <4829b7ea$0$2672$bb690d87@news.main-rheiner.de>

Ben Morrow wrote:
> Quoth Thomas Kratz <ThomasKratz@REMOVEwebCAPS.de>:
>> A. Sinan Unur wrote:
>>
>>> package My::Constants;
>>>
>>> use strict;
>>> use warnings;
>>>
>>> use base qw( Exporter );
>>>
>>> our @EXPORT = qw();
>>> our @EXPORT_OK = qw( ONE TWO THREE );
>>>
>>> use constant ONE => 'one';
>>> use constant TWO => 'two';
>>> use constant THREE => 'three';
>>>
>>> 1;
>> I just needed that last week for a module but found the:
>>
>>   our @EXPORT_OK = qw( ONE TWO THREE );
>>
>> a bit tedious when you are having many constants. I had to play around a 
>> bit and found you can do (maybe that's obvious, but it wasn't to me):
>>
>>   my %constant_hash;
>>   BEGIN {
>>     %constant_hash = (
>>       ONE   => 'one',
>>       TWO   => 'two',
>>       THREE => 'three',
>>     };
>>   }
>>   our @EXPORT_OK   = keys %constant_hash;
>>   our %EXPORT_TAGS = (
>>      constants => [keys %constant_hash],
>>   );
> 
> There's no need for the BEGIN block: since this is a 'use'd module,
> everything will happen at BEGIN time anyway.
> 
>     require constant;
> 
>     my %constants = (
>         ONE => 'one',
>         TWO => 'two',
>     );
> 
>     our (@EXPORT_OK, %EXPORT_TAGS);
> 
>     for (keys %constants) {
>         constant->import($_ => $constants{$_});
>         push @{ %EXPORT_TAGS{constants} }, $_;
>     }
>     push @EXPORT_OK, @{ %EXPORT_TAGS{constants} };

You are right if you call constant->import. I think for using

  use constant \%constants;

%constants must be filled in a BEGIN block.

Thomas

-- 
$/=$,,$_=<DATA>,s,(.*),$1,see;__END__
s,^(.*\043),,mg,@_=map{[split'']}split;{#>J~.>_an~>>e~......>r~
$_=$_[$%][$"];y,<~>^,-++-,?{$/=--$|?'"':#..u.t.^.o.P.r.>ha~.e..
'%',s,(.),\$$/$1=1,,$;=$_}:/\w/?{y,_, ,,#..>s^~ht<._..._..c....
print}:y,.,,||last,,,,,,$_=$;;eval,redo}#.....>.e.r^.>l^..>k^.-


------------------------------

Date: Tue, 13 May 2008 12:13:18 -0400
From: Bernie Cosell <bernie@fantasyfarm.com>
Subject: Re: Constants across package boundaries
Message-Id: <j1fj245rv3otun12id6ap3ordg54jjcul3@library.airnews.net>

"A. Sinan Unur" <1usa@llenroc.ude.invalid> wrote:

} bernie@fantasyfarm.com wrote in news:85c5f60e-9834-43d0-8d8b-
} 9d955c663db0@c58g2000hsc.googlegroups.com:
} 
} > I've been chasing a compile problem  and I just saw the light on what
} > my trouble is: I use a bunch of "use constant this => ...; use
} > constant that =>...;" to set parameters for the program.  BUT: the
} > program uses a 'package' or two [it has a small embedded objects in
} > it]. ...

} The proper way to do this would be to set up a package for all your 
} constants and use it from any file that needs any of those constants.

That's true, but the sylistic/management problem I'm starting from is that
I want this program to be a *single*file* not a little cluster of files
that have to be moved around together.  That's the same reason I ran into
this problem: the "little object" I've set up is just *right*in* the plain
 .pl file.  Just {   package MyLittleObject;
                      [objectstuff]
                }
right in the main file [and basically the same reason I have the POD docs
in the same file, also.

} Keep in mind that constants defined using the constant pragma are not 
} variables but subroutines.

I know.  It got ugly enough using those constants in print strings that I
started using the
    print "This is a constant @{[CONS]}\n"
construct...

} In any case, here is how to do it:
} 
} E:\Home\asu1\Src\Test> cat My\Constants.pm
} package My::Constants;

Is there a way to do this *locally*, in the same file.  That is, at the
start of my .pl file, I had just a block of:
   
    use constant THIS => xxx;
    use constant THAT => yyy;
     ...

It is no problem at all making that:
    {   package constants ;
        use Exporter ;
        our EXPORT_OK(qw(THIS THAT THEOTHER)) ;
        use constant THIS =>
         ...etc.
    }
but how would I then "import" that package's exports into my main program
and into the one or two "package regions" in it?  Can I just later on do
     constants::import(qw(var1 var2 var3));
???

  /Bernie\
-- 
Bernie Cosell                     Fantasy Farm Fibers
bernie@fantasyfarm.com            Pearisburg, VA
    -->  Too many people, too few sheep  <--          


------------------------------

Date: Tue, 13 May 2008 12:13:18 -0400
From: Bernie Cosell <bernie@fantasyfarm.com>
Subject: Re: Constants across package boundaries
Message-Id: <buej24pbali6vc20lgfvlu8ahn4v1pv82q@library.airnews.net>

Ben Morrow <ben@morrow.me.uk> wrote:

} Quoth bernie@fantasyfarm.com:
} > use Exporter 'import' ;

} > 
} > "import" is not exported by the Exporter module at test.pl line 6
} 
} Does the manpage you're using match your version of Exporter? The
} ability to import (rather than inherit) Exporter::import was not present
} in older versions of Exporter.

Ah.  I bet that's it: the "system" version of perl is still 5.6 but I
expect that when I do "man Exporter" I get the 5.8 man page.  [*ONE* Of
these days they'll install 5.8...:o)]

  /B\
-- 
Bernie Cosell                     Fantasy Farm Fibers
bernie@fantasyfarm.com            Pearisburg, VA
    -->  Too many people, too few sheep  <--          


------------------------------

Date: Tue, 13 May 2008 18:55:19 +0100
From: Ben Morrow <ben@morrow.me.uk>
Subject: Re: Constants across package boundaries
Message-Id: <791pf5-ji91.ln1@osiris.mauzo.dyndns.org>


Quoth Bernie Cosell <bernie@fantasyfarm.com>:
> 
> Is there a way to do this *locally*, in the same file.  That is, at the
> start of my .pl file, I had just a block of:
>    
>     use constant THIS => xxx;
>     use constant THAT => yyy;
>      ...
> 
> It is no problem at all making that:
>     {   package constants ;
>         use Exporter ;
>         our EXPORT_OK(qw(THIS THAT THEOTHER)) ;
>         use constant THIS =>
>          ...etc.
>     }
> but how would I then "import" that package's exports into my main program
> and into the one or two "package regions" in it?  Can I just later on do
>      constants::import(qw(var1 var2 var3));
> ???

I would do it like this:

    BEGIN {
        package My::Constants;  # don't use all-lowercase package names:
                                # they are reserved for pragmata

        $INC{'My/Constants.pm'} = $0;   # tell perl we've loaded this
                                        # module

        use Exporter;
        our @EXPORT_OK = ...;

        use constant ...;
    }

    use My::Constants qw/foo bar baz/;

Setting the entry in $INC (at compile time) means that 'use' now just
performs an import at compile time.

Alternatively, yes,

    BEGIN { My::Constants->import(qw/foo bar/) }

will work perfectly well (note that import is a *method*, not a
function).

Ben

-- 
   If you put all the prophets,   |   You'd have so much more reason
   Mystics and saints             |   Than ever was born
   In one room together,          |   Out of all of the conflicts of time.
ben@morrow.me.uk                                    The Levellers, 'Believers'


------------------------------

Date: Tue, 13 May 2008 15:09:42 GMT
From: "A. Sinan Unur" <1usa@llenroc.ude.invalid>
Subject: Re: How to pass around an Array of Arrays (or Array Refs)
Message-Id: <Xns9A9D7189F342Casu1cornelledu@127.0.0.1>

jerrykrinock@gmail.com wrote in news:14236a89-69f8-4b1a-bf24-
095e9cd0db9d@p25g2000hsf.googlegroups.com:

> I need to pass an array of arrays from a function, but I can't make an
> array of arrays work.  Actually, I've got better results making an
> array of array references.  Here's what I've done:
> 
> #!/usr/bin/perl
> 
> my @array ;
> my @row ;
> @row = ('a00', 'a01') ;
> push (@array, \@row) ;
> @row = ('a10', 'a11') ;
> push (@array, \@row) ;
> @row = ('a20', 'a21') ;
> push (@array, \@row) ;

Would it be easier to understand if I changed the above to:

my $array_ref = [ 
   [ qw( a00 a01 ) ],
   [ qw( a10 a11 ) ],
   [ qw( a20 a21 ) ],
];

In what you wrote above, you are pushing the reference to the same array 
(@row) and you keep overwriting the contents of @row. So, now you have 
three references pointing to the exact same array.

#!/usr/bin/perl

use strict;
use warnings;

my @array;

my @row = ('a00', 'a01') ;
push (@array, \@row) ;
@row = ('a10', 'a11') ;
push (@array, \@row) ;
@row = ('a20', 'a21') ;
push (@array, \@row) ;

print "$_\n" for @array;

__END__

E:\Home\asu1\Src\Test> s1
ARRAY(0x182a2fc)
ARRAY(0x182a2fc)
ARRAY(0x182a2fc)


-- 
A. Sinan Unur <1usa@llenroc.ude.invalid>
(remove .invalid and reverse each component for email address)

comp.lang.perl.misc guidelines on the WWW:
http://www.rehabitation.com/clpmisc/


------------------------------

Date: Tue, 13 May 2008 16:24:30 GMT
From: Jürgen Exner <jurgenex@hotmail.com>
Subject: Re: How to pass around an Array of Arrays (or Array Refs)
Message-Id: <m4gj245oai1uainp9k4shoqpk5h4n3nhgr@4ax.com>

jerrykrinock@gmail.com wrote:
>I need to pass an array of arrays from a function, but I can't make an
>array of arrays work.  

That's because you can't. The argument list as well as the return value
of a function is a flat sequence of scalars. It is impossible to pass an
array of arrays (or list of arrays for that matter).

>Actually, I've got better results making an
>array of array references.  Here's what I've done:

And that's exactly what you should be doing.

jue


------------------------------

Date: 6 Apr 2001 21:33:47 GMT (Last modified)
From: Perl-Users-Request@ruby.oce.orst.edu (Perl-Users-Digest Admin) 
Subject: Digest Administrivia (Last modified: 6 Apr 01)
Message-Id: <null>


Administrivia:

#The Perl-Users Digest is a retransmission of the USENET newsgroup
#comp.lang.perl.misc.  For subscription or unsubscription requests, send
#the single line:
#
#	subscribe perl-users
#or:
#	unsubscribe perl-users
#
#to almanac@ruby.oce.orst.edu.  

NOTE: due to the current flood of worm email banging on ruby, the smtp
server on ruby has been shut off until further notice. 

To submit articles to comp.lang.perl.announce, send your article to
clpa@perl.com.

#To request back copies (available for a week or so), send your request
#to almanac@ruby.oce.orst.edu with the command "send perl-users x.y",
#where x is the volume number and y is the issue number.

#For other requests pertaining to the digest, send mail to
#perl-users-request@ruby.oce.orst.edu. Do not waste your time or mine
#sending perl questions to the -request address, I don't have time to
#answer them even if I did know the answer.


------------------------------
End of Perl-Users Digest V11 Issue 1540
***************************************


home help back first fref pref prev next nref lref last post