How to execute nested Perl commands in same line - perl

I am new to perl , Is it any way to write nested perl commands in single line like below (shell)
echo "I am `uname -n` and today is `date`"
I tried like below ; but not working
my $i=0 ;
print "$i++\n" ;
print "localtime()" ;

You can only interpolate variables into double-quoted strings. But those variables can be anonymous, allowing you to provide an expression to generate them. This looks like this:
my $i = 0;
print "Number ${\($i++)} date ${\scalar localtime}";
You can also use #{[ some-expression ]} instead of ${\ some-expression }. In either case, you have an expression and you create a reference to its value (or in the former case, to an anonymous array containing it), and then dereference it in the string. The expression will be in list context, so you may need to add scalar, as above.

Is it any way to write nested perl commands in single line like below (shell)
Of course you can.
print "I am " . `uname -n` . "and today is " . `date`;
Perl's backtick operator (`) doesn't work inside double quotes (""). So, the string "I am ", the output of uname -n, the string "and today is " and the output of date are joined by dot operator (.).
I don't understand what the latter part of your question means in relation to the former part (and I think ysth has already answered to it).

Related

Not sure of the reason for output value

I have these two statements in a perl code that I'm trying to understand.
our $CSITOOLS=`/x/eng/csitools/netapp_menu/common/csitools.sh`;
print "${CSITOOLS}\n";
Output:
/x/eng/csitools
How does ${VARIABLE_NAME} work? (In this case {CSITOOLS})
Thanks!
From perldata:
As in some shells, you can enclose the variable name in braces
to disambiguate it from following alphanumerics (and underscores).
That is:
If you have a variable like $foo and you want to interpolate that whithin a string:
my $string = "This is $foobar";
then Perl would look for the variable $foobar. To make clear your variable's name
is just $foo you need to write
my $string = "This is ${foo}bar";
This is the way to delimit the variable's name. In your particular case the curlies {} aren't needed because "$CSITOOLS\n" already is unambiguous. However, it does no harm.
Perl allows you to surround the name of a scalar variable with braces ({}) to separate its name from any surrounding characters. Imagine you have the word "item" in a variable, and you want to print item99 within a string, with no whitespace in between:
my $name = "item";
print "${name}99\n";
Without the braces, perl would interpret the variable like this:
print "$name99\n";
...which is an undeclared, undefined variable, and definitely not what you mean. With warnings enabled, would display something like:
Use of uninitialized variable in ...
If warnings are not enabled, the program may merrily run along and do other things, possibly/likely breaking something far down the line. That makes things really difficult to troubleshoot.
In your simple case, the braces aren't needed, and you don't see them all that very often in print statements, unless you need to combine variables where there's no whitespace character between it and other valid variable characters when interpolating within a string.
From perldoc.perl.org
A string enclosed by backticks (grave accents) first undergoes double-quote interpolation. It is then interpreted as an external command, and the output of that command is the value of the backtick string, like in a shell.
Apparently, the result of csitools.sh is the string /x/eng/csitools

Cannot get correct return value in sprintf function call

My problem is that the return value im printing is not being translated into a value.
I have the following code in a test file.
#!/usr/bin/perl -I/srv/www/jonathan/m/www
my $var = sprintf("$%.1f lbs",(77*2.20462));
print $var;
Its returning: 0.1f instead of the value i need to see.
What am i doing incorrectly here? I'm a perl newbie.
Your problem is that Perl interprets "$%.1f" as the variable $% followed by ".1f". $% is a special Perl variable containing "The current page number of the currently selected output channel" (see perlvar) and that has the value 0, so what gets printed is the string "0.1f".
There are a few ways round this.
You can remove the dollar sign: sprintf("%.1f lbs",(77*2.20462)). But that changes the string that you display.
You can escape the dollar to tell Perl that it's not special: sprintf("\$%.1f lbs",(77*2.20462)).
But I think there's a better solution. Perl treats dollar signs as special characters in double-quoted strings. But there's no reason for your string to be double-quoted. So just change your format string to use single quotes: sprintf('$%.1f lbs',(77*2.20462)).
That last one is the solution I'd use.
Perl uses dolar($) symbol to declare a scalar variable, you need to remove the $ symbol from the sprintf.
corrected code
my $var = sprintf("%.1f lbs",(77*2.20462));
print $var;
output
169.8 lbs

Behavior of . and , operators in Perl for concatenation and parsing

I was trying to play with the . and , operators in Perl and got something weird which I was unable to figure out:
If I run this:
print hello . this,isatest, program
the output is:
hellothisisatestprogram
What I could understand is that it is treating both the text before and after the dot operator as string and concatenating them.
But what about the commas? Why is it getting omitted and not concatenated?
First period (.) is treated as concatenation operator. Subsequent commas separate multiple parameters of print. The result is the same - all parts are concatenated. If you want to print literal commas, enclose this,isatest, program in quotes - "this,isatest, program" to form single argument.
http://perldoc.perl.org/functions/print.html
I think this is what you want:
perl -e 'print "hello"." this,isatest,program"."\n"'
Run above code and check the output. If it gives you desired output then I guess we have an explanation.

Split by dot using Perl

I use the split function by two ways. First way (string argument to split):
my $string = "chr1.txt";
my #array1 = split(".", $string);
print $array1[0];
I get this error:
Use of uninitialized value in print
When I do split by the second way (regular expression argument to split), I don't get any errors.
my #array1 = split(/\./, $string); print $array1[0];
My first way of splitting is not working only for dot.
What is the reason behind this?
"\." is just ., careful with escape sequences.
If you want a backslash and a dot in a double-quoted string, you need "\\.". Or use single quotes: '\.'
If you just want to parse files and get their suffixes, better use the fileparse() method from File::Basename.
Additional details to the information provided by Mat:
In split "\.", ... the first parameter to split is first interpreted as a double-quoted string before being passed to the regex engine. As Mat said, inside a double-quoted string, a \ is the escape character, meaning "take the next character literally", e.g. for things like putting double quotes inside a double-quoted string: "\""
So your split gets passed "." as the pattern. A single dot means "split on any character". As you know, the split pattern itself is not part of the results. So you have several empty strings as the result.
But why is the first element undefined instead of empty? The answer lies in the documentation for split: if you don't impose a limit on the number of elements returned by split (its third argument) then it will silently remove empty results from the end of the list. As all items are empty the list is empty, hence the first element doesn't exist and is undefined.
You can see the difference with this particular snippet:
my #p1 = split "\.", "thing";
my #p2 = split "\.", "thing", -1;
print scalar(#p1), ' ', scalar(#p2), "\n";
It outputs 0 6.
The "proper" way to deal with this, however, is what #soulSurfer2010 said in his post.

How can I prevent Perl from interpreting \ as an escape character?

How can I print a address string without making Perl take the slashes as escape characters? I don't want to alter the string by adding more escape characters also.
What you're asking about is called interpolation. See the documentation for "Quote-Like Operators" at perldoc perlop, but more specifically the way to do it is with the syntax called the "here-document" combined with single quotes:
Single quotes indicate the text is to be treated literally with no interpolation of its content. This is similar to single quoted strings except that backslashes have no special meaning, with \ being treated as two backslashes and not one as they would in every other quoting construct.
This is the only form of quoting in perl where there is no need to worry about escaping content, something that code generators can and do make good use of.
For example:
my $address = <<'EOF';
blah#blah.blah.com\with\backslashes\all\over\theplace
EOF
You may want to read up on the various other quoting operators such as qw and qq (at the same document as I referenced above), as they are very commonly used and make good shorthand for other more long-winded ways of escaping content.
Use single quotes. For example
print 'lots\of\backslashes', "\n";
gives
lots\of\backslashes
If you want to interpolate variables, use the . operator, as in
$var = "pesky";
print 'lots\of\\' . $var . '\backslashes', "\n";
Notice that you have to escape the backslash at the end of the string.
As an alternative, you could use join:
print join("\\" => "lots", "of", $var, "backslashes"), "\n";
We could give much more helpful answers if you'd give us sample code.
It depends what you're escaping, but the Quote-like operators may help.
See the perlop man page.
Use the backslah two times,
print "This is a backslah character \\";