What's the point of blessed in Perl? - perl

[root# ~]$ perl -e "print 1 if blessed $a;"
1
[root# ~]$ perl -e "print 1 if blessed $c;"
1
[root# ~]$ perl -e "print 1 if blessed $cee;"
1
It seems always true,the version is 5.8.8.
UPDATE
I'm not running as root, it's CHANGED by me for the sake of privacy:)

blessed is not a keyword in Perl. You are using double quotes in your shell command, so the variables ($a, $c, etc.) are from your shell's environment, they are not Perl variables.
Since these environment variables are probably empty, you are essentially executing the script
print 1 if blessed ;
When used like this, blessed is just a bareword string and always evaluates to true. What you have done is not much difference from running
$ perl -e 'print 1 if foo'

Do you mean blessed from Scalar::Util? You probably want to load the function first:
perl -MScalar::Util=blessed -e "print 1 if blessed $a;"
otherwise your blessed is just bareword (string), which is obviously true.

As has been pointed out, you need to load the module before using the method. Also, if you had used perl -we instead of perl -e, you would probably not have asked this question.
For me, with perl -we, I get this warning:
Can't call method "blessed" without a package or object reference at -e line 1.

Related

xargs pass multiple arguments to perl subroutine?

I know how to pipe multiple arguments with xargs:
echo a b | xargs -l bash -c '1:$0 2:$1'
and I know how to pass the array of arguments to my perl module's subroutine from xargs:
echo a b | xargs --replace={} perl -I/home/me/module.pm -Mme -e 'me::someSub("{}")'
But I can't seem to get multiple individual arguments passed to perl using those dollar references (to satisfy the me::someSub signature):
echo a b | xargs -l perl -e 'print("$0 $1")'
Just prints:
-e
So how do I get the shell arguments: $0, $1 passed to my perl module's subroutine?
I know I could just delimit a;b so that the xarg {} could be processed by perl splitting it to get individual arguments), but I could also just completely process all STDIN with perl. Instead, my objective is to use perl -e so that I can explicitly call the subroutine I want (rather than having some pre-process in the script that figures out what subroutine to call and what arguments to use based on STDIN, to avoid script maintenance costs).
While bash's argument are available as $# and $0, $1, $2, etc, Perl's arguments are available via #ARGV. This means that the Perl equivalent of
echo a b | xargs -l bash -c 'echo "1:$0 2:$1"'
is
echo a b | xargs -l perl -e'CORE::say "1:$ARGV[0] 2:$ARGV[1]"'
That said, it doesn't make sense to use xargs in this way because there's no way to predict how many times it will call perl, and there's no way to predict how many arguments it will pass to perl each time. You have an XY Problem, and you haven't provided any information to help us. Maybe you're looking for
perl -e'CORE::say "1:$ARGV[0] 2:$ARGV[1]"' $( echo a b )
I am not sure about the details of your design, so I take it that you need a Perl one-liner to use shell's variables that are seen in the scope in which it's called.
A perl -e'...' executes a Perl program given under ''. For any variables from the environment where this program runs -- a pipeline, or a shell script -- to be available to the program their values need be passed to it. Ways to do this with a one-liner are spelled out in this post, and here is a summary.
A Perl program receives arguments passed to it on the command-line in #ARGV array. So you can invoke it in a pipeline as
... | perl -e'($v1, $v2) = #ARGV; ...' "$0" "$1"
or as
... | xargs -l perl -e'($v1, $v2) = #ARGV; ...'
if xargs is indeed used to feed the Perl program its input. In the first example the variables are quoted to protect possible interesting characters in them (spaces, *, etc) from being interpreted by the shell that sets up and runs the perl program.
If input contains multiple lines to process and the one-liner uses -n or -p for it then unpack arguments in a BEGIN block
... | perl -ne'BEGIN { ($v1, $v2) = splice(#ARGV,0,2) }; ...' "$0" "$1" ...
which runs at compile time, so before the loop over input lines provided by -n/-p. The arguments other than filenames are now removed from #ARGV, so to leave only the filenames there for -n/-p, in case input comes from files.
There is also a rudimentary mechanism for command-line switches in a one-liner, via the -s switch. Please see the link above for details; I'd recommend #ARGV over this.
Finally, your calling code could set up environment variables which are then available to the Perl progam in %ENV. However, that doesn't seem to be suitable to what you seem to want.
Also see this post for another example.

What is the difference between uppercase "-E" switch and lowercase "-e" in perl?

How does the perl switches "-E" and "-e" differ from each other? In this example they works exactly the same — executes the command after the switch:
$ perl -e 'print "$_\n" foreach 1..2'
1
2
$ perl -E 'print "$_\n" foreach 1..2'
1
2
This is explained in perldoc perlrun:
-E commandline
behaves just like -e, except that it implicitly enables all optional features (in the main compilation unit). See feature.
The "See feature." refers to the documentation for the feature pragma, which you can read by typing perldoc feature.
-E unlike -e enables features
You can check what these are using Deparse module (following is for perl 5.16),
perl -MO=Deparse -E 1
use feature 'current_sub', 'evalbytes', 'fc', 'say', 'state', 'switch', 'unicode_strings', 'unicode_eval';
From Perldoc:http://perldoc.perl.org/perlrun.html
•-e commandline :
may be used to enter one line of program. If -e is given, Perl will not look for a filename in the argument list. Multiple -e commands may be given to build up a multi-line script. Make sure to use semicolons where you would in a normal program.
•-E commandline :
behaves just like -e, except that it implicitly enables all optional features (in the main compilation unit). See feature.

executing perl code from commandline in windows

i am very new to perl just began to learn when i try to assign a scalar a value and the print it i am facing problem. I am doing
perl -e "$number=30;"
perl -e "print $number;"
the output doesnt show anything but when i do
perl -e "$number=30; print $number;"
the output shows 30 why?
This:
perl -e "$number=30;"
runs the Perl program $number=30;, which sets the variable $number to 30 and then does nothing with it.
This:
perl -e "print $number;"
runs the Perl program print $number;, which prints the value of the uninitialized variable $number.
The key point is that, since these are two completely separate Perl programs, there's no connection between the variable $number in the first program and the variable $number in the second program. There is no relationship between the two programs, and no communication between them, so they do not and cannot share any variables.
when you execute:
perl -e "$number=30;"
perl -e "print $number;"
these are two independent processes, so they don't share information. Variable $number won't be available to the second command.
The other one:
perl -e "$number=30; print $number;"
Works because it runs in the same execution, and $number is visible to the next print sentence

perl doing different things on two different platforms

On Mac OSX, this works fine with perl
perl -v
This is perl, v5.8.9 built for darwin-2level
perl -e 'sub test {}'
But on Solaris
perl -v
This is perl, v5.8.8 built for i86pc-solaris-thread-multi
perl -e 'sub test {}'
Illegal declaration of anonymous subroutine at -e line 1.
Any ideas?
Thanks,
Kelly
It's most likely a behavior difference between the two versions of Perl. It's also probably just a bug in the CLI evaluation mode in 5.8.8
Try this test to see if it's just the CLI evaluation or Perl itself:
use strict;
sub test {}
If it passes strict mode in a file, it's probably as good as it's gonna get.
perldoc perldiag says:
Illegal declaration of anonymous subroutine
(F) When using the sub keyword to construct an anonymous subroutine,
you must always specify a block of code. See perlsub
It's could possibly be in a sitecustomize.pl file. It's not seeing the "test". It's reading it as 'sub'. Try typing perl -e 'test {}' on the command line.
Also to take out the customization file, you could add the -f switch to the command line. `perl -fe 'sub test {}'
perldoc perlrun for more information.

How can I combine two conditions in Perl?

I have two Perl one liners:
perl -pe "s/\b$a\b/$b/g if m/param1 /" test
and
perl -pe "s/\b$a\b/$b/g unless /^#/" test
How can I combine theif m/somthing/ and the unless /something/, like:
[root#localhost tmp]# perl -pe "s/\b$a\b/$b/g if m/param1/ unless /^#/" test
syntax error at -e line 1, near "m/param1/ unless"
Maybe
perl -pe "s/\b$a\b/$b/g if m/param1/ && ! /^#/" test
does it.
unless is the same as if not. Judging by the way you've written the statement, I'm guessing you mean the following:
perl -pe "s/\b$a\b/$b/g if m/param1/ and not /^#/" test
(Although, you might have meant or instead of and?)
On an unrelated note, you may want to add the \Q and \E escape sequences around $a in your regex:
perl -pe "s/\b\Q$a\E\b/$b/g if m/param1 /" test
They escape any characters that are special to regexes. If you intend for $a to hold a regex you should probably move the word boundary assertions (\b) into it.
No matter what you choose to do, you will need to be careful with values in $a and $b. For instance:
a="/"
b="slash"
perl -pe "s/\b\Q$a\E\b/$b/g if m/param1 /" test
will cause a syntax error. One solution to this is to not use environment variables to replace code. Perl allows you access to the environment through the %ENV hash:
perl -pe 's/\b\Q$ENV{a}\E\b/$ENV{b}/g if m/param1 /' test
Notice the use of single ticks to avoid treating $ENV as a shell variable.