I'm writing a perl script and I would like to pass a file name for the output file to a subroutine.
I tried something like this:
use strict;
use warnings;
test("Output.dat");
sub test {
my $name = @_;
open(B, ">$name") or die "Failure \n";
print B "This is a test! \n";
close(B);
}
I'm going to use the subroutine multiple times, so i have to pass the file name and cannot declare it within the subroutine.
I hope you can help me :)
Your problem is this line:
my $name = @_;
You are assigning an array to a scalar variable. In Perl this will give you the number of elements in the array - so I expect you're ending up with "1" in $name
.
There are a number of ways to get the first element from an array;
my $name = $_[0]; # Explicitly get the first element
my $name = shift @_; # Get the first element (and remove it from the array)
my $name = shift; # Same as the previous example - shift works on @_ by default in a subroutine
my ($name) = @_; # The parentheses make it into a list assignment
The last two are the ones that you will see most commonly.
A few more points:
1/ You would get a better clue to the problem if you included $name
in your error message.
open(A, ">$name") or die "Failure: $name \n";
Or, even better, the error message that Perl gets from your operating system.
open(A, ">$name") or die "Could not open $name: $!\n";
(I've added back the missing comma - I assume that was a typo.)
2/ This days, it is generally accepted as good practice to use the three-arg version of open
and lexical filehandles.
open(my $output_fh, '>', $name) or die "Failure: $name \n";
3/ In your example you open a filehandle called "A", but then try to write to a filehandle called "B". Is this a typo?
my $name = @_;
Will assign to $name
value of @_
in scalar mode. It means number of elements in array _
. It is a number of arguments. It is most probably not what you would like. So you have to assign an array to an array or a scalar to a scalar. You have two options
my $name = $_[0];
or
my ($name) = @_; # or even (my $name) = @_;
Where I would prefer later because it can be easily modified to my ($a, $b, $c) = @_;
and it is Perl idiom.
But your code has more flaws. For example, you should use this open
form
open my $fd, '>', $name or die "cannot open > $name: $!";
This has few advantages. The first, you use lexical scoped IO handle which prevents leaking outside of the lexical scope and is automatically closed when exits this lexical scope. The second, list form prevents interpretation of $name
content other than file name.
So resulting code should look like:
sub test {
my ($name) = @_;
open my $fd, '>', $name
or die "cannot open > $name: $!";
print $fd "This is a test!\n";
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With