Perl syntax error printing list index - perl

I am trying to print an index of a list returned from a function call. I am wrapping the function call in parenthesis in an attempt to convert the list to an array. The program fails to compile saying 'syntax error at file.pl line 4, near ")["'. If I create a temporary variable $a or use printf indexing is fine. Why does print brake, is there a better alternative?
sub get{
return (1,2);
}
#print (get())[0]; #fails
printf("%d",(get())[0]);
my $a = (get())[0];
print $a;

I assume that you are foolishly not using
use warnings;
Which is quite a bad thing to not do. If you had used it, you would get the warning:
print (...) interpreted as function
Which is to say, what you wrote
print (get())[0]
Is something Perl interprets as you trying to put a subscript on the print() function. This does not work.
For the code to do what you expect, you need to be explicit about the parentheses:
print ( (get())[0] );
You should always use
use strict;
use warnings;
There is a slight learning curve to using these, but they only show you your errors. Not using them only hides your errors, and your code does not work better.

Try this :
sub get{
return (1,2);
}
print((get)[0]);
or
my $a = (get)[0];
print $a;
OUTPUT
1

Related

Facing issue using map function in perl

I have the below lines:
7290741.out:Info: /test doesn't exist, Running on Network location
7300568.out:sh: /tmp/test/1234_123_test/test1/test2/abc.txt: bad interpreter
I have these lines in an array #test1.
I want to fetch only the numbers before .out and put them in an array #test2.
I used the below code for this:
foreach my $test1(#test1) {
my #test2;
map { /(d+)\.out/ and push #test2, $1 } <$error>;
print "#test2\n";
}
But, when I execute the code, it is printing complete lines, and I want the output like below:
7290741
7300568
Can someone please help?
When I ran your code, I just got 2 blank lines of output.
Regardless, here is a simpler version of your code which just prints out the numbers:
use warnings;
use strict;
my #test1;
while (<DATA>) {
chomp;
push #test1, $_;
}
my #test2;
for (#test1) {
push #test2, $1 if /(\d+)\.out/;
}
for (#test2) {
print "$_\n";
}
__DATA__
7290741.out:Info: /test doesn't exist, Running on Network location
7300568.out:sh: /tmp/test/1234_123_test/test1/test2/abc.txt: bad interpreter
There are numerous problems with your code.
You should use warnings and strict.
The $error variable was not defined in the code you posted.
d in the regular expression should have been \d.
You should have declared the #test2 variable outside the foreach loop; otherwise, it would only have a single value due to variable scoping.
my #nums = map { /^(\d+)\.out/ } <$errors>
Is the simplest way to put it, using map. When you try to first read the errors into an array (#test1) and loop around those values, and inside the loop try to read the values again, you are doing the same thing twice. map is also a loop.
This is assuming that your file with errors is what the filehandle $errors is reading from. Remember also to always use
use strict;
use warnings;
Perhaps OP is looking for solution of following form
Explanation:
<DATA> in this context will represent an array of lines
map will form a loop through lines
regex extracts portion of information OP interested in
result is stored in #test array
NOTE: Data::Dumper is used only for the result visualization
#!/usr/bin/env perl
#
# vim: ai ts=4 sw=4
use strict;
use warnings;
use feature 'say';
use Data::Dumper;
my #test = map { /^(.*?).out/ } <DATA>;
say Dumper(\#test);
__DATA__
7290741.out:Info: /test doesn't exist, Running on Network location
7300568.out:sh: /tmp/test/1234_123_test/test1/test2/abc.txt: bad interpreter
Output
$VAR1 = [
'7290741',
'7300568'
];

Why do I get a syntax error in my compound if statement?

Why do I get a syntax error in the following script?
print "Enter Sequence:";
$a = <STDIN>;
if ($a=="A")|| ($a== "T")|| ( $a == "C")|| ($a== "G")
{
print $a;
}
else
{
print "Error";
}
First, you have a syntax error: The condition expression of an if statement must be in parens.
The second error is found by using use strict; use warnings;, something you should always do. The error is the use of numerical comparison (==) where string comparison (eq) is called for.
The final problem is that $a will almost surely contain a string ending with a newline, so a chomp is in order.
The immediate problem is that he entire logical expression for an if must be in parentheses.
In addition
You must use eq instead of == for comparing strings
Your input string will have a trailing newline, so it will look like "C\n" and will not match a simple one-character string. You need to chomp the input before you compare it
It is generally better to read from STDIN using <> rather than <STDIN>. That way you can specify an input file on the command line, or read from the STDIN if no input was provided
You must always put use strict and use warnings at the top of your program. That will catch many simple errors that you may otherwise overlook
You shouldn't use $a as a variable name. It is a symbol reserved by Perl itself, and says nothing about the purpose of the variable
It is best to use a regular expression for simple comparisons like this. It makes your code much easier to read and will usually make the execution very much faster
Please take a look at this program, which I think does what you want.
use strict;
use warnings;
print "Enter Sequence: ";
my $input = <>;
chomp $input;
if ( $input =~ /^[ATCG]$/i ) {
print $input, "\n";
}
else {
print "Error";
}

Perl script for creating two arrays

Input: A list of numbers on command line
Output: Two lists of numbers ,one with input numbers that are greater than zero and one with those that are less than zero (Ignoring zero valued numbers)
here is my code
#!/usr/bin/perl
$i++ = 0;
$j++ = 0;
while ($number = <>)
{
if($number<0)
$first[$i++]=$number;
else
$second[$j++]=$number;
}
print "The numbers with value less than zero are\n";
foreach $number (#first)
print $number;
print "The numbers with value greater than zero are\n"
foreach $number(#second)
print $number;
I am getting the following silly errors which i am not able to rectify.The errors are
divide.pl: 2: ++: not found
divide.pl: 3: ++: not found
divide.pl: 5: Syntax error: ")" unexpected
Can anybody help me out with rectifying these errors please? I am new to perl script
Curly braces on compound statements are not optional in Perl.
Your statements:
$i++=0;
$j++=0;
don't make sense; you probably just want to delete the "++".
You're missing a semicolon on one of your print statements.
Once you've got those problems fixed, you should add
use strict;
use warnings;
after the #! line. This will introduce more error messages; you'll need to fix those as well. For example, you'll need to declare your variables using my().
The code you present will hardly compile. Loops should have {} around the main block, arrays are better created with push (or unshift), you should use strict and warnings, and you can't do increments at the same time as assignments (e.g. $i++ = 0).
use v5.10;
use strict;
use warnings;
my (#first, #second);
while (<STDIN>) { # <STDIN> clearer than <> in this case
chomp;
if ($_ < 0) {
push #first, $_;
} elsif ($_ > 0) {
push #second, $_;
}
}
say "Numbers less than zero:";
say "#first";
say "Numbers greater than zero:";
say "#second";
I don't know what $i++ = 0 is supposed to mean, but change that to $i = 0 to initialize the variables.
Also, the first thing yuu should do in the while loop is call chomp($number) to remove spurious newlines - 5\n is not a number and treating it as one will confuse perl.
Once you've fixed that, post any new errors that show up - I don't see any other problems though.
How are you executing this perl script? Beyond the errors mentioned about the code itself. It looks like you are attempting to evaluate the code using dash instead of perl.
The errors you should be seeing if you were executing it with Perl would be like:
Can't modify postincrement (++) in scalar assignment at /tmp/foo.pl
line 2, near "0;"
But instead, your errors are more in line with what dash outputs:
$ dash /tmp/foo.pl
/tmp/foo.pl: 2: ++: not found
/tmp/foo.pl: 3: ++: not found
Once you've verified that you are running your perl script properly you can start working through the other problems people have mentioned your code. The easiest way to do this is to run it via perl divide.pl instead of whatever you are doing.

perl print array from subroutine

#! /usr/local/bin/perl
sub getClusters
{
my #clusters = `/qbo/bin/getclusters|grep -v 'qboc33'`;
chomp(#clusters);
return \#clusters;
}
ummm okay .. how do I get at this array to print since ...
foreach $cluster (getClusters())
{ print $cluster."\n"; }
doesn't seem to work.
Thanks.
You are returning a reference, and not dereferencing it anywhere.
foreach $cluster (#{getClusters()})
OR
return #clusters;
Either should fix it (with slightly different effects), with the first one being preferred (your array is kind of big).
You'd use the non-referenced array return for limited number of elements, usually for the purpose of multi-return (thus, usually, limited to 2 or 3, known-length arrays).
If you ran your program under use strict; use warnings;, it would have told you why it failed. As Amadan said, you need to dereference the reference you return.
Perl Solution
#!/usr/local/bin/perl
use strict;
use warnings;
main();
sub main{
{
local $" = "\n";
print "#{getClusters()}";
}
}
sub getClusters{
my #tArray = `/qbo/bin/getclusters|grep -v 'qboc33'`;
chomp #tArray;
return \#tArray;
}
Notice
You don't need a foreach loop for debugging, you can just reset the $" operator however to separate array elements however you like (eg, , , , or how I set it in the code above \n).
Returning an array ref is a plus, don't send back the full array (good job)
use strict/warnings, especially when debugging
try to avoid system calls using ``
To make it easy, you can first receive the return value and then print it like
use strict;
use warning;
my $cluster_array = getClusters();
my #cluster_return = #{$cluster_array};
foreach my $cluster(#cluster_return){
print"$cluster\n";
}

Why can't I say print $somehash{$var}{fh} "foo"?

I have a line of code along the lines of:
print $somehash{$var}{fh} "foo";
The hash contains the filehandle a few levels down. The error is:
String found where operator expected at test.pl line 10, near "} "foo""
I can fix it by doing this:
my $fh = $somehash{$var}{fh};
print $fh "foo";
...but is there a one-liner?
see http://perldoc.perl.org/functions/print.html
Note that if you're storing
FILEHANDLEs in an array, or if you're
using any other expression more
complex than a scalar variable to
retrieve it, you will have to use a
block returning the filehandle value
instead: ...
So, in your case, you would use a block like this:
print { $somehash{$var}{fh} } "foo";
If you have anything other than a simple scalar as your filehandle, you need to wrap the reference holding the filehandle in braces so Perl knows how to parse the statement:
print { $somehash{$var}{fh} } $foo;
Part of Perl Best Practices says to always wrap filehandles in braces just for this reason, although I don't get that nutty with it.
The syntax is odd because print is an indirect method on a filehandle object:
method_name Object #arguments;
You might have seen this in old-school CGI.pm. Here are two indirect method calls:
use CGI;
my $cgi_object = new CGI 'cat=Buster&bird=nightengale';
my $value = param $cgi_object 'bird';
print "Indirect value is $value\n";
That almost works fine (see Schwern's answer about the ambiguity) as long as the object is in a simple scalar. However, if I put the $cgi_object in a hash, I get the same syntax error you got with print. I can put the braces around the hash access to make it work out. Continuing with the previous code:
my %hash;
$hash{animals}{cgi} = $cgi_object;
# $value = param $hash{animals}{cgi} 'cat'; # syntax error
$value = param { $hash{animals}{cgi} } 'cat';
print "Braced value is $value\n";
That's all a bit clunky so just use the arrow notation for everything instead:
my $cgi_object = CGI->new( ... );
$cgi_object->param( ... );
$hash{animals}{cgi}->param( ... );
You can do the same with filehandles, although you have to use the IO::Handle module to make it all work out:
use IO::Handle;
STDOUT->print( 'Hello World' );
open my( $fh ), ">", $filename or die ...;
$fh->print( ... );
$hash{animals}{fh} = $fh;
$hash{animals}{fh}->print( ... );
The above answers are all correct. The reason they don't allow a full expression in there is print FH LIST is already pretty weird syntax. To put anything more complicated in there would introduce a ton of ambiguous syntax. The block removed that ambiguity.
To see where this madness leads to, consider the horror that is indirect object syntax.
foo $bar; # Is that foo($bar) or $bar->foo()? Good luck!