A little spacing and expansion helps:
perl -ne '$& && print( $_ ), $_ =~ m/default|$/'
Take that one step at a time...
-n tells Perl to loop over the input, line by line, placing each line into $_, one line per iteration.
$& is the special variable that contains the string matched in the most recent pattern match. On the first iteration $_ is set to the first line, but $& is empty because we haven't yet executed a match.
&& is the short-circuit operator. It evaluates the LHS first. If the LHS is false (no value, or zero), it skips the right hand side. But if the lefthand side is true (contains a value that is non-zero, and not the empty string) it evaluates (executes) the right-hand side. On the right hand side is 'print'.
On the first iteration (as mentioned before), $& is empty, thus false. So nothing gets printed. Then the comma operator moves us along to the regexp matching. If $_ matches /default|$/, $& gets a value, and if it matched the 'default' portion of the alternation in the regexp, on the next iteration, the logical short-circuit will be true. And that being the case, the contents of $_ (on the next iteration) will be printed.
Some of this will make more sense if you have a look at perlrun and perlvar. This is what they're talking about when they say that Perl has a rich and compact syntax.
| [reply] [d/l] [select] |
Thanks for your help. The reason it was so confusing was the '$&' and '&&' can/were pushed together ($&&&) and it worked the same way. Now we can use the following to print the matched line and the line after the matched line.
perl -ne '$&&&print($&,"\n",$_), /default|$/'
Thanks again for you quick and very helpful response.
J | [reply] [d/l] |
If $& is true print $_; then match against $_ looking for either "default" or the end of the line. As a side effect, this match will set $& either to "default" (a true value) or the empty string (a false value).
| [reply] [d/l] [select] |