ProgrammingThis forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.
Notices
Welcome to LinuxQuestions.org, a friendly and active Linux Community.
You are currently viewing LQ as a guest. By joining our community you will have the ability to post topics, receive our newsletter, use the advanced search, subscribe to threads and access many other special features. Registration is quick, simple and absolutely free. Join our community today!
Note that registered members see fewer ads, and ContentLink is completely disabled once you log in.
If you have any problems with the registration process or your account login, please contact us. If you need to reset your password, click here.
Having a problem logging in? Please visit this page to clear all LQ-related cookies.
Get a virtual cloud desktop with the Linux distro that you want in less than five minutes with Shells! With over 10 pre-installed distros to choose from, the worry-free installation life is here! Whether you are a digital nomad or just looking for flexibility, Shells can put your Linux machine on the device that you want to use.
Exclusive for LQ members, get up to 45% off per month. Click here for more info.
Now I am wondering, if its possible to have an array statement like this :
@printers=(`cat /tmp/test_print1`);
I just dont want to use the other way (eg open (FH, "< $file") or die "Can't open $file for read: $!" and am wondering if its possible to do something like the above (cat), to populate the array?
If you know that the file "printerlist" has only a group of lines like that (one item per line, printer names only), you could also do something like this:
Code:
#!/usr/bin/perl
use warnings;
use strict;
my @printers;
while (<>) {
chomp;
push @printers, $_;
}
## Code here to work on @printers array ##
Save this as "printers_perl" and put the filename "printerlist" in the command line when you run it: ./printers_perl printerlist
If you know that the file "printerlist" has only a group of lines like that (one item per line, printer names only), you could also do something like this:
Code:
#!/usr/bin/perl
use warnings;
use strict;
my @printers;
while (<>) {
chomp;
push @printers, $_;
}
## Code here to work on @printers array ##
If you want to do that anyway, you could just slurp it:
Code:
chomp(my @printers=<>);
## Code here to work on @printers array ##
Btw, the act of slurping a file without explicitly opening a filehandle and checking to make sure it opened is going to be a built-in feature in Perl 6 (whenever that gets released. You will also be able to specify automatic chomping.
So you will be able to do this:
Code:
my @printers = slurp('/tmp/test_print1', {chomp=>1});
## Code here to work on @printers array ##
If you want this in perl 5, you’ll need to “use Perl6::Slurp” to get the same functionality.
So you want to slurp two separate files? Because of the way the default filehandle (“<>”) works, the first slurp will slurp the entirety of ALL the files specified in @ARGV. The second slurp will just wait for more input (presumably from STDIN). There are a few remedies to this problem:
Go back to using the non-portable `cat filename` construct.
Use Perl6::Slurp.
Go about opening filehandles, and slurp them individually. This is not always as annoying as it seems:
Code:
my ($printers, $print_servers) = do {
open(my $pr, $ARGV[0]) && open(my $ps, $ARGV[1]) || die "$!";
([<$pr>], [<$ps>]);
};
# use $printers and $print_servers as array references (e.g., $printers->[0], etc.)
So pretty much three lines, and it doesn’t look too bad. If you notice, $pr and $ps go out of scope after the block, so the files are automatically closed. A downside (not too problematic) is that you get array references instead of real arrays.
Manipulate @ARGV, and then slurp. The default filehandle “<>” picks input from the files listed in @ARGV, and if there are no such files, then from STDIN. So if you manipulate @ARGV prior to slurping, you can control what happens to it. So (assuming you want the first file in @printers and the second in @print_servers), you might do something like:
Code:
my $temp=pop @ARGV;
chomp(my @printers=<>);
push(@ARGV,$temp);
chomp(my @print_servers=<>);
If you don’t want $temp to litter the namespace, you could probably pull off putting the construct in a “do” block.
If you are sure that the files are the same size, you can use slices to access them directly:
Code:
chomp(my @both=<>);
my @printers=@both[0..@both/2-1];
my @print_servers=@both[@both/2..$#both];
Obviously, this is the most error-prone (e.g., there will be no errors if you happen to be unable to read one of the files, or if you just forget to specify a file).
Btw, you can use hash-slicing to accomplish the same thing as your for loop. So this:
Code:
my %hash;
for my $i (0..$#printers) {
$hash{$printers[$i]} = $print_servers[$i];
}
Is equivalent to this:
Code:
my %hash;
@hash{@printers}=@print_servers;
Last edited by osor; 02-16-2008 at 12:13 PM.
Reason: typo
I completely forgot a simpler (sort of) method: Have the first file as an argument and the second file redirected to STDIN. So you could do something like what you did before:
As a general rule, I like to look for CPAN-modules to do things like this, because the writers of those modules usually are thinking, "how can I do this in a portable, system-independent way?" If you port your program over to Windows, it won't run anymore. Maybe that is not a consideration; maybe it is.
Secondly... as you can see from this thread, "there's more than one way to do it." Pick one, comment it clearly, and make sure that it works in all of the present-and-future situations that your code is likely to encounter. Then, move along to the next objective in your project. "There's more than one way to do it," and you don't have to enumerate them.
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.