Perl :what does "-" means in perl - perl

what does '-' mean in the param
$cgi->start_html(-title => uc($color), -BGCOLOR => $color);
I just know it is used in hash type, but this is param in a sub. So it makes me confused, and i searched for a long time.

Whenever you come across confusing syntax in Perl, a handy tool is the -MO=Deparse option. This causes Perl to check the syntax of a script and output the script in a normalized form, rather than executing it.
So if I do
perl -MO=Deparse -e '$cgi->start_html(-title => uc($color), -BGCOLOR => $color);'
I get a result of:
$cgi->start_html(-'title', uc $color, -'BGCOLOR', $color);
-e syntax OK
There are three differences here:
Quotes were added to title and BGCOLOR.
The => operators changed to commas.
The parentheses disappeared from uc($color).
The first two are the normal effects of the => ("fat comma") operator: It's equivalent to a comma, except that if the thing to the left is an identifier (starting with a letter or underscore and containing only alphanumeric characters and underscores), that identifier becomes a quoted string.
And the parentheses after uc just aren't strictly necessary in this situation, since the builtin function uc is prototyped to take 0 or 1 arguments.
But now we have -'title' and -'BGCOLOR', so what's the negative of a string? Checking perldoc perlop, we see that unary minus follows the rules:
If the operand is a number or a string representation of a number, does an arithmetic negation.
Otherwise, if the string starts with '+' or '-', switches just the first character of the string to the opposite sign.
Otherwise, if the string starts with a letter, adds a '-' to the beginning of the string.
Otherwise, attempts to convert the string to a number, probably prints a warning if warnings are enabled, and then does an arithmetic negation.
Here we have case 3, so -'title' is '-title' and -'BGCOLOR' is '-BGCOLOR'.
So presumably the start_html method expects a list of arguments which come in key-value pairs, and the key strings are supposed to start with hyphens. (It might or might not internally use these arguments to create a hash, with a line like my %options = #_;.)
This is all a little roundabout, plus you'd get confusing results if you ever tried passing something like -3zzz => $value. So I'd personally add explicit quotes here to make it obvious what's being passed, but keep using the fat commas anyway to emphasize the arguments are meant to be key/value pairs:
$cgi->start_html('-title' => uc($color), '-BGCOLOR' => $color);

It has no effect here. It's just treated as part of the string. I assume that the original author of CGI.pm wanted to make the options look more like command-line options. I think that was a terrible idea.

It's a string literal, just like "-title" or "-BGCOLOR".

perldoc perlop:
[Unary "-" ...] If the operand is an identifier, a string consisting of a minus sign concatenated with the identifier is returned. Otherwise, if the string starts with a plus or minus, a string starting with the opposite sign is returned.
In other words, -"foo" is "-foo".
The => operator (sometimes pronounced "fat comma") is a synonym for the comma except that it causes a word on its left to be interpreted as a string if it begins with a letter or underscore and is composed only of letters, digits and underscores.
In other words, foo => 42 is "foo", 42.
Taken together, this means -title => uc($color) is "-title", uc($color).

Related

Not able to understand a command in perl

I need help to understand what below command is doing exactly
$abc{hier} =~ s#/tools.*/dfII/?.*##g;
and $abc{hier} contains a path "/home/test1/test2/test3"
Can someone please let me know what the above command is doing exactly. Thanks
s/PATTERN/REPLACEMENT/ is Perl's substitution operator. It searches a string for text that matches the regex PATTERN and replaces it with REPLACEMENT.
By default, the substitution operator works on $_. To tell it to work on a different variable, you use the binding operator - =~.
The default delimiter used by the substitution operator is a slash (/) but you can change that to any other character. This is useful if your PATTERN or your REPLACEMENT contains a slash. In this case, the programmer has used # as the delimiter.
To recap:
$abc{hier} =~ s#PATTERN#REPLACEMENT#;
means "look for text in $abc{hier} that matches PATTERN and replace it with REPLACEMENT.
The substitution operator also has various options that change its behaviour. They are added by putting letters after the final delimiter. In this case we have a g. That means "make the substitution global" - or match and change all occurrences of PATTERN.
In your case, the REPLACEMENT string is empty (we have two # characters next to each other). So we're replacing the PATTERN with nothing - effectively deleting whatever matches PATTERN.
So now we have:
$abc{hier} =~ s#PATTERN*##g;
And we know it means, "in the variable $abc{hier}, look for any string that matches PATTERN and replace it with nothing".
The last thing to look at is the PATTERN (or regular expression - "regex"). You can get the full definition of regexes in perldoc perlre. But to explain what we're using here:
/tools : is the fixed string "/tools"
.* : is zero or more of any character
/dfII : is the fixed string "/dfII"
/? : is an optional slash character
.* : is (again) zero or more of any character
So, basically, we're removing bits of a file path from a value that's stored in a hash.
This =~ means "Do a regex operation on that variable."
(Actually, as ikegami correctly reminds me, it is not necessarily only regex operations, because it could also be a transliteration.)
The operation in question is s#something#else#, which means replace the "something" with something "else".
The g at the end means "Do it for all occurences of something."
Since the "else" is empty, the replacement has the effect of deleting.
The "something" is a definition according to regex syntax, roughly it means "Starting with '/tools' and later containing '/dfII', followed pretty much by anything until the end."
Note, the regex mentions at the end /?.*. In detail, this would mean "A slash (/) , or maybe not (?), and then absolutely anything (.) any number of times including 0 times (*). Strictly speaking it is not necessary to define "slash or not", if it is followed by "anything any often", because "anything" includes as slash, and anyoften would include 0 or one time; whether it is followed by more "anything" or not. I.e. the /? could be omitted, without changing the behaviour.
(Thanks ikeagami for confirming.)
$abc{hier} =~ s#/tools.*/dfII/?.*##g;
The above commands use regular expression to strip/remove trailing /tools.*/dfII and
/tools.*/dfII/.* from value of hier member of %abc hash.
It is pretty basic perl except non standard regular expression limiters (# instead of standard /). It allows to avoid escaping / inside the regular expression (s/\/tools.*\/dfII\/?.*//g).
My personal preferred style-guide would make it s{/tools.*/dfII/?.*}{}g .

Why are leading-hyphen options permitted on `use` lines without fat comma and with strict?

Why is the following use line legal Perl syntax? (Adapted from the POD for parent; tested on Perl 5.26.2 x64 on Cygwin.)
package MyHash;
use strict;
use Tie::Hash;
use parent -norequire, "Tie::StdHash";
# ^^^^^^^^^^ A bareword with nothing to protect it!
Under -MO=Deparse, the use line becomes
use parent ('-norequire', 'Tie::StdHash');
but I can't tell from the use docs where the quoting on -norequire comes from.
If use strict were not in force, I would understand it. The bareword norequire would become the string "norequire", the unary minus would turn that string into "-bareword", and the resulting string would go into the use import list. For example:
package MyHash;
use Tie::Hash;
use parent -norequire, "Tie::StdHash";
Similarly, if there were a fat comma, I would understand it. -foo => bar becomes "-foo", bar because => turns foo into "foo", and then the unary minus works its magic again. For example:
package MyHash;
use strict;
use Tie::Hash;
use parent -norequire => "Tie::StdHash";
Both of those examples produce the same deparse for the use line. However, both have quoting that the original example does not. What am I missing that makes the original example (with strict, without =>) legal? Thanks!
You already cited perldoc perlop, but it is relevant here.
Unary - performs arithmetic negation if the operand is numeric, including any string that looks like a number. If the operand is an identifier, a string consisting of a minus sign concatenated with the identifier is returned. ... One effect of these rules is that -bareword is equivalent to the string "-bareword".
This behavior of the unary minus operator is applied to the bareword before the strict checks are applied. Therefore, unary minus is a kind of quoting operator that also works in strict mode.
Similarly, barewords as the invocant in method invocation do not need to be quoted as long as they are not a function call:
Foo->bar; # 'Foo'->bar(); --- but only if no sub Foo exists
print->bar; # print($_)->bar();
However, the unary minus behaviour seems to be due to constant folding, not due to a special case in the parser. For example, this code
use strict;
0 ? foo : bar;
will only complain about the bareword "bar" being disallowed, suggesting that the bareword check happens very late during parsing and compilation. In the unary minus case, the bareword will already have been constant-folded into a proper string value at that point, and no bareword remains visible.
While this is arguably buggy, it is also impossible to change without breaking backwards compatibility – and this behaviour is used by many modules such as use parent to communicate options. Compare also similar idioms on command line interfaces, where options usually begin with a dash.
From perlop
Symbolic Unary Operators
Unary "-" performs arithmetic negation if the operand is numeric, including any
string that looks like a number. If the operand is an identifier, a string
consisting of a minus sign concatenated with the identifier is returned.
Otherwise, if the string starts with a plus or minus, a string starting with
the opposite sign is returned. One effect of these rules is that -bareword is
equivalent to the string "-bareword". If, however, the string begins with a
non-alphabetic character (excluding "+" or "-"), Perl will attempt to convert
the string to a numeric and the arithmetic negation is performed. If the string
cannot be cleanly converted to a numeric, Perl will give the warning Argument
"the string" isn't numeric in negation (-) at ....
So because of the rules of Perl parsing -name is treated as "-name" even under use strict

Difference between /.../ and m/.../ in Perl

What is difference between /.../ and m/.../?
use strict;
use warnings;
my $str = "This is a testing for modifier";
if ($str =~ /This/i) { print "Modifier...\n"; }
if ($str =~ m/This/i) { print "W/O Modifier...\n"; }
However, I checked with this site for Reference not clearly understand with the theory
There's no difference. If you just supply /PATTERN/ then it assumes m. However, if you're using an alternative delimiter, you need to supply the m. E.g. m|PATTERN| won't work as |PATTERN|.
In your example, i is the modifier as it's after the pattern. m is the operation. (as opposed to s, tr, y etc.)
Perhaps slightly confusingly - you can use m as a modifier, but only if you put if after the match.
m/PATTERN/m will cause ^ and $ to match differently than in m/PATTERN/, but it's the trailing m that does this, not the leading one.
Perl has a number of quote-like operators where you can choose the delimiter to suit the data you're passing to the operator.
q(...) creates a single-quoted string
qq(...) creates a double-quoted string
qw(...) creates a list by splitting its arguments on white-space
qx(...) executes a command and returns the output
qr(...) compiles a regular expression
m(...) matches its argument as a regular expression
(There's also s(...)(...) but I've left that off the list as it has two arguments)
For some of these, you can omit the letter at the start of the operator if you choose the default delimiter.
You can omit q if you use single quote characters ('...').
You can omit qq if you use double quote characters ("...").
You can omit qx if you use backticks (`...`).
You can omit m if you use slashes (/.../).
So, to answer your original question, m/.../ and /.../ are the same, but because slashes are the default delimitor for the match operator, you can omit the m.

What does =~/^0$/ mean in Perl?

I'm new to Perl and I have been learning about the Perl basics for past two days.
I'm converting a Perl script to Java program gradually.
In the Perl script, I came across this code.
if( $arr[$i]=~/^0$/ ){
...
...
}
I know that $arr[$i] means getting the ith element from the array arr.
But what does =~/^0$/ mean?
To what are they comparing the array's element?
I searched for this, but I couldn't find it.
Someone please explain me.
FYI, the arr contains floating values.
if ($arr[$i]) =~ /^0$/) is roughly equivalent to if ($arr[$i] eq "0"), but not exactly the same, as it will match both the strings "0" and "0\n". If $arr[$1] was read from a file or stdin and it has not been chomped, this can be a very significant distinction.
if ($arr[$i] == 0), on the other hand, will match any string beginning with a non-numeric character or a string of zeroes/whitespace which is not followed by a numeric character, although it will generate a warning if the string contains non-whitespace, non-digit characters or contains only whitespace (and warnings are enabled, of course).
=~ is a binding operator.
"Binary "=~" binds a scalar expression to a pattern match"
/^0$/ on the right hand side is the regex
^ Match the beginning of the line
$ Match the end of the line (or before newline at the end)
And the zero has no special meaning.
^ and $ are regex anchors which says $arr[$i] should begin with 0 and there is end of string immediately after it.
It can be written as
if ($arr[$i] eq "0" or $arr[$i] eq "0\n")

Funky 'x' usage in perl

My usual 'x' usage was :
print("#" x 78, "\n");
Which concatenates 78 times the string "#". But recently I came across this code:
while (<>) { print if m{^a}x }
Which prints every line of input starting with an 'a'. I understand the regexp matching part (m{^a}), but I really don't see what that 'x' is doing here.
Any explanation would be appreciated.
It's a modifier for the regex. The x modifier tells perl to ignore whitespace and comments inside the regex.
In your example code it does not make a difference because there are no whitespace or comments in the regex.
The "x" in your first case, is a repetition operator, which takes the string as the left argument and the number of times to repeat as the right argument. Perl6 can replicate lists using the "xx" repetition operator.
Your second example uses the regular expression m{^a}x. While you may use many different types of delimiters, neophytes may like to use the familiar notation, which uses a forward slash: m/^a/x
The "x" in a regex is called a modifier or a flag and is but one of many optional flags that may be used. It is used to ignore whitespace in the regex pattern, but it also allows the use of normal comments inside. Because regex patterns can get really long and confusing, using whitespace and comments are very helpful.
Your example is very short (all it says is if the first letter of the line starts with "a"), so you probably wouldn't need whitespace or comments, but you could if you wanted to.
Example:
m/^a # first letter is an 'a'
# <-- you can put more regex on this line because whitespace is ignored
# <-- and more here if you want
/x
In this use case 'x' is a regex modifier which "Extends your pattern's legibility by permitting whitespace and comments." according to the perl documentation. However it seems redundant here