views:

388

answers:

3

I'm parsing XML files with something like:

while (<files/*.xml>) { ... }

I want to use a constant to 'files', say

use constant FILES_PATH => 'files';
while (<FILES_PATH/*.xml>) { ... }

I hope you understand the idea, and can help me :)..

Thank you in advance.

A: 

Surely "/" in this context would be treated as division and that is not likely to go anywhere. I think you might need to step back a bit and look at what other options you have. I think you are trying to do "file globbing" and I seem to recall support in perl for that though I do not recall the details. There is a "Glob" module in CPAN which you may want to look at. Personally I would be a lot more pedestrian and just use DirHandle and filter out non-xml files with an "next ... unless ..." line.

asparagus
No, the contents of <> are treated like a double quoted string if it is not a file handle, so / has no special meaning. This is also why you can't just use the constant (constants don't interpolate), but the old dereferencing-an-anonymous-array-to-include-a-function-call works. opendir+readdir+grep+closedir is a valid answer, but often a glob is simpler to read (especially if you use Readonly instead of the constant pragma).
Chas. Owens
+6  A: 

Hmm, this is one reason to use Readonly instead of constant. You may be able to use & the start or () at the end of the constant to get Perl to realize it is subroutine. Let me check.

Nope, but you can use the classic trick of creating an arrayref to dereference:

#!/usr/bin/perl

use strict;
use warnings;

use constant DIR => "/tmp";

print map { "$_\n" } <${[DIR]}[0]/*>;

But since glob "*" is the same as <*> you may prefer:

#!/usr/bin/perl

use strict;
use warnings;

use constant DIR => "/tmp";

print map { "$_\n" } glob DIR . "/*";

I would probably say

#!/usr/bin/perl

use strict;
use warnings;

use Readonly;

Readonly my $DIR => "/tmp";

print map { "$_\n" } <$DIR/*>;
Chas. Owens
So complete, but I have no Readonly module available :(.. will use just the glob option.
grilix
Readonly is on CPAN, do a search for how to setup CPAN on your OS or, if you are using Linux, look at the packages available in your distribution (Readonly has most likely been packaged for you). In Ubuntu it is named libreadonly-perl
Chas. Owens
A: 

As others have said, this is all about string interpolation.

The constant pragma fails in interpolative contexts, so you have to use something that will work.

As already mentioned, Readonly is one option.

You can also use the old "assign a read-only value to a typeglob trick".

our $FILES_PATH; # declare FILES_PATH scalar to keep strict happy.
*FILES_PATH = \'files';  # Assign to typeglob so $FILES_PATH points to a string literal  

while( <$FILES_PATH/*.xml> ) {
    # read the files
}
daotoad