Beefy Boxes and Bandwidth Generously Provided by pair Networks
"be consistent"
 
PerlMonks  

On patterns and more

by Sary (Novice)
on Mar 06, 2011 at 12:24 UTC ( [id://891673]=perlquestion: print w/replies, xml ) Need Help??

Sary has asked for the wisdom of the Perl Monks concerning the following question:

Hey there, and thanks for your time, here it is: $_ What is that? I've done some reading and could not understand that variable? Operator?

Also being very new to perl, I stumble with the =~ operator..

The following code should check the array for persons of certain lastname and pring only them.

@myNames = ('Larry jackson', 'Curly jackson', 'Moe Sanders'); print "Who's on the list:\n"; foreach (@myNames) { if($_ =~ "jackson") print $_ . "\n"; }
And what is that dot after the $_ thing? man.....

If someone could clarify the above for me please. Also this be my first post on the monastery, so thrash me lightly :]

Replies are listed 'Best First'.
Re: On patterns and more
by ELISHEVA (Prior) on Mar 06, 2011 at 12:57 UTC

    $_ is a variable that is set to whatever Perl thinks you are most likely to want to use as a default command/subroutine argument. Many Perl commands will automatically use whatever value is assigned to $_ so you don't have to do so much typing:

    defined #same as defined($_) print #same as print STDOUT $_ /\sjackson$/ #same as $_ =~ /\sjackson$/

    The actual value assigned to $_ depends on the context because what you are "most likely to want to use as an argument" usually depends on what you are doing in your code at that moment.

    In a for loop $_ is the current array element.

    When using grep or map it is also the current array element:

    @only_defined = grep { defined($_) } @somearray; %hash_defined = map { $_ => 1 } @only_defined; #and since $_ is the default argument, you can also write @only_defined = grep { defined } @somearray; @only_begins_with_a = grep { /^a/ } @somearray;

    If you are reading from a file using the <> operator, it is the most recently read line, e.g.

    while (<STDIN>) { chomp # same as chomp $_ if (/^#/) {....} # same as if ($_ =~ /^#/) { ....} }

    You don't have to use $_ for loops. In fact, for production code, it is a good idea not to because every so often something you are doing inside the for loop might unexpectedly reset $_ (it shouldn't but you don't always have control over other people's code and how they use things like $_. The inside of loops often makes calls to other people's code). For example, your loop above could also have been written:

    #Note this code still won't work - see sherm's explanation below. foreach my $name (@myNames) { if($name =~ "jackson") print $name . "\n"; #sic - should be { print $name . "\n" } }

    The same caution about $_ also applies to $_ when reading from an input stream or any other use of $_. If you are doing something complicated, it is best to assign $_ to a variable with a name you control and to use that variable instead of $_. Thus a better way to write the code reading from STDIN above would be

    while (my $line = <STDIN>) { chomp $line; if ($line =~ /^#/) {....} }

    Update: added comment about non-working code and referenced sherm's explanation below.

Re: On patterns and more
by Sherm (Sexton) on Mar 06, 2011 at 13:05 UTC

    Okay, first things first: What is $_? Simply put, it's a variable. In that sense, it's no different than $foo or $bar. What makes it special is that it's used it by default in many situations, if you don't supply another variable. The chomp() function, for example, which removes $/ (which is typically \n) from the end of one or more variables. If you write chomp($foo), it will affect $foo; but if you write chomp(), it will affect $_ by default.

    Another example of using $_ is the foreach() loop in your own code. Foreach creates a local alias for each element in the given list. Because you didn't specify a name for that alias, it defaults to using $_. But, you could have written that as "foreach my $thisName (@myNames)", in which case the $thisName variable would be used as the alias instead.

    The problem in your loop actually isn't the pattern match - that does just what you think it should, matching only strings that contain "jackson". The problem is that you've left out the curly braces. Unlike C, Perl's curly braces are always required for compound statements. So you need to write that if() like this:

    if ($_ =~ "jackson") { print $_ . "\n"; }

    That's only relevant when you're using a statement that requires a code block, though, as in "if() { ... }" - there are alternatives you can use that wouldn't require one, such as a logical-and operator or statement modifiers. (Note that these examples take advantage of the fact that the match operator m// also defaults to matching against $_!)

    m/jackson/ and print $_ . "\n"; # logical-and print $_ . "\n" if (m/jackson/); # statement modifier
    Finally (whew!) the . operator does string concatenation. That is, "foo" . "bar" will result in "foobar".
Re: On patterns and more
by ikegami (Patriarch) on Mar 06, 2011 at 17:12 UTC
    There's nothing special about $_ per say.
    for (@names) { # Use $_ here }

    is simply the same as

    for $_ (@names) { # Use $_ here }

    You can use a different variable if you want

    for my $name (@names) { # Use $name here }
Re: On patterns and more
by Khen1950fx (Canon) on Mar 07, 2011 at 08:12 UTC
    What is that?

    There are a couple of tricks to help you answer that. Since $_ has been defined, start with that. Using perldoc, just enter

    perldoc -v '$_'
    It'll return the info for $_. Note that you'll need to use single-quotes around $_ to avoid interpolation.

    $_ is a perl builtin variable, but how would you know that? You can get a complete list of builtin variables by using B::Keywords:

    #!/usr/bin/perl use strict; use warnings; use B::Keywords qw(:all); print join "\n", @Symbols, "\n";
    What if you encounter a function that you don't know? Using perldoc, enter, for example, the function "my":
    perldoc -f my
    To get a categorized list of functions, you'll use Pod::Functions. You'll need to enter the complete path to your Pod::Functions:
    perl /usr/lib/perl5/5.8.8/Pod/Functions.pm
    I'm not aware of a quick and easy way to get perl's operators.

    Update: ELISHEVA has reminded me that you can access perlop by entering doc://perldoc in the perlmonk's search bar.

Re: On patterns and more
by chrestomanci (Priest) on Mar 06, 2011 at 20:28 UTC

    I am sure the answers to your questions are in more or less every Perl related FAQ. $_ will be documented in perlvar, =~ will be in perlop, but this is a quiet Sunday evening, and I enjoy helping out Novice monks.

    I think $_ has been adequately explained by ELISHEVA, I especially liked her explanation of it as ...whatever Perl thinks you are most likely to want...

    =~ is the operator that binds a perl scalar variable to a regular expression. If you are not using $_, This is usually how you tell perl what variable you want to test against the regular expression. Consider ELISHEVA's second example:

    while (<STDIN>) { chomp # same as chomp $_ if (/^#/) {....} # same as if ($_ =~ /^#/) { ....} }

    With explicit variables this could be written:

    while (my $line = <STDIN>) { chomp $line; # same as chomp $_ if ( $line =~ m/^#/ ) { # Action on $line. } }

    In this form we have made the code a good deal clearer, and easier to understand by a novice, But because we are no longer using the $_ default variable we need to tell perl what variable the regular expression should be matched with. The whole $variable =~ m/regexp/ returns true if the variable matches regular expression, or false otherwise, so within an if statement it allows you to select only lines that match.

    The other use for the =~ operator is for substitutions. If you write:

    $line =~ s/^#/# Comment /;

    Then you substitute everything that matches on the left with the string on the right. In this case any lines in the input that start with hash will have 'Comment' prepended.

Re: On patterns and more
by cmac (Monk) on Mar 07, 2011 at 03:37 UTC
    • To match for jackson you can say m"jackson" or /jackson/. With slashes the m is assumed.
    • You don't need the $_ =~ because $_ is the assumed operand of a match.
    • The dot is concatenation. If you don't like it you can say "$_\n"
Re: On patterns and more
by BrimBorium (Friar) on Mar 06, 2011 at 19:15 UTC

      Not at all. It relates to the match, substitution and tr operators, not regular expressions. Some of those operators take a regular expression for argument, but that's unrelated to «=~».


      «=~» is the means by which one specifies the operand (argument) for some operators.

      $x =~ m/.../ # Matches against $x $x =~ s/.../.../ # Modifies $x $x =~ tr/.../.../ # Modifies $x

      «/.../» is short for «m/.../».

      Operators that support «=~» default to using «$_» if «=~» isn't' used. For example, «/.../» is short for «$_ =~ /.../».

      The match operator is implied if the RHS of «=~» is an expression, so «$x =~ "pat"» means «$x =~ /pat/» and «$x =~ $pat» means «$x =~ /$pat/».

Re: On patterns and more
by perliff (Monk) on Mar 09, 2011 at 13:09 UTC
    Ok, let me rewrite your code for you in a simpler way... You want to match in the "second" name if I get it right.. avoiding matching people who might be called Jackson Anything or Jackson Something or perhaps, even just jackson. I have put comments in the code itself.
    my @myNames = ('Larry jackson', 'Curly jackson', 'Moe Sanders','Jackso +n Something','jackson',); # our list of names, note that I added a few more print "Who's on the list:\n"; foreach $fullname (@myNames) { # $fullname contains each name in @myNames one by one @array = split (/\s+/,$fullname); # lets split the name based on a whitespace character, # in our case, a space, \s if (scalar @array > 1) { # if the number of elements in the array @array # is more than one, which it should be, then # check the second element, like this if($array[1] =~ /jackson/i) { # the "i" indicates a case-insensitive match, # Jackson is same as jackson print "$fullname\n"; # go ahead and print } } }

    perliff

    ----------------------

    -with perl on my side

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://891673]
Approved by Corion
Front-paged by chrestomanci
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others surveying the Monastery: (9)
As of 2024-04-18 20:37 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found