Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is _ (single underscore) in Perl without $ or @?

Tags:

perl

I have some code like this:

if (!-d _ || !-o _ || ($vncUserDirUnderTmp && ($mode & 0777) != 0700)) {     raise Exception("$prog: Wrong type or access mode of $vncUserDir.\n") } 

I could find information about @_ and $_ in Perl but not about _ alone. What does it mean in -d _ and -o _ here?

like image 645
Kim Avatar asked Sep 14 '17 09:09

Kim


People also ask

What is underscore in Perl?

To improve legibility, Perl allows you to use an underscore character instead. The underscore only works within literal numbers specified in your program, not in strings functioning as numbers or in data read from somewhere else. Similarly, the leading 0x for hex and 0 for octal work only for literals.

What is$@ in Perl?

$@ The Perl syntax error or routine error message from the last eval, do-FILE, or require command. If set, either the compilation failed, or the die function was executed within the code of the eval.

What does ~= mean in Perl?

=~ is the Perl binding operator and can be used to determine if a regular expression match occurred (true or false) $sentence = "The river flows slowly."; if ($sentence =~ /river/) { print "Matched river.\n"; } else { print "Did not match river.\n"; } Follow this answer to receive notifications.


2 Answers

When used with a filetest (-X) operator the stat structure of the previous file test is used

If any of the file tests (or either the stat or lstat operator) is given the special filehandle consisting of a solitary underline, then the stat structure of the previous file test (or stat operator) is used, saving a system call.
...
Example:

stat($filename);   print "Readable\n" if -r _;   print "Writable\n" if -w _; ... 

So in your example !-d _ tests whether the file last stat-ed isn't a directory.

Update  

The unusual _ is really a typeglob *_ but with operators expecting a filehandle the * may be omitted, like <*STDIN> may be written as <STDIN>. It is found in the symbol table

print *{$main::{_}}{IO}, "\n";   # -->  IO::Handle=IO(0x2311970) 

In a one-liner the *_ gets set up only after calls to stat and _ are made.

like image 129
zdim Avatar answered Oct 01 '22 04:10

zdim


When you call one of the file test operators (-f, -d, -s, etc) Perl actually makes a call to the operating system's stat function. The stat function returns a structure full of all sorts of interesting information about the file in question, but each of the file test operators only looks at one of the fields from that structure (is it a file? is it a directory? how big is it?)

It's common that you might want to know more that one piece of information about a file (is it a file? can I read it? can I execute it?) The naive way to write that is:

if (-f $file and -r $file and -x $file) 

But that makes three calls to stat - with each one of them only looking at one of the fields from the structure. To mitigate that, Perl is clever and caches the results of the most recent call to stat. It is cached against the special filehandle _. So a more efficient way to write the same code is:

if (-f $file and -r _ and -x _) 

That only makes one call to stat.

Since Perl 5.10, you can also use "stacked file tests" and write this code as:

if (-x -r -f $file) # Note reversed order of operators 

Update: perldoc says this about stacked file operators.

As of Perl 5.10.0, as a form of purely syntactic sugar, you can stack file test operators, in a way that -f -w -x $file is equivalent to"-x $file && -w _ && -f _. (This is only fancy syntax: if you use the return value of -f $file as an argument to another filetest operator, no special magic will happen.)

like image 22
Dave Cross Avatar answered Oct 01 '22 03:10

Dave Cross