A. Raj A. Raj - 4 years ago 149
Perl Question

Need help understanding this Perl snippet

I'm reading Learning Perl (6th edition) and came upon a code snippet that I couldn't decipher. One of the exercises after chapter 14 asks to build a program that takes as input a string and a substring then finds the indices at which the substring occurs in the string.

Here's the way I did it:

print "Enter a string: ";
chomp($string = <STDIN>);

print "Enter a substring: ";
chomp($sub = <STDIN>);

until ($index == -1) {
print $index, "\n" if defined($index);
$index = index($string, $sub, $index + 1);

In the answers section, they show two ways. One is easy to understand and similar to mine, but the other is purposefully obfuscating:

print "Enter a string: ";
chomp($string = <STDIN>);

print "Enter a substring: ";
chomp($sub = <STDIN>);

for (my $pos = –1; –1 !=
($pos = index
push @places, ((((+$pos))))) {
'for ($pos != 1; # ;$pos++) {
print "position $pos\n";#;';#' } pop @places;

print "Locations of '$sub' in '$string' were: @places\n";

I have almost no idea what's going on in that for loop. I know it's of the form
for (initialize; test; increment)
and that it's testing that the index is not -1, which means no more occurrences of the substring. But what's going on with the assignment to $pos? Why are there so many parentheses around +$pos? What's going on after the many parentheses? I'd really appreciate it if someone could walk me through the second part. Please keep in mind I've just started learning Perl a week ago.

BTW, I tried running their code but it gave me this error:

Unrecognized character \xE2; marked by <-- HERE after my $pos = <-- HERE near column 16 at ex14.obfs.pl line 1.

Answer Source

I've simplified your example just a little bit, discarded the useless junk and comments. Hope now it is clear what's going on:

print "Please enter a string: ";
chomp(my $string = <STDIN>);
print "Please enter a substring: ";
chomp(my $sub = <STDIN>);

my @places;

for (my $pos = -1; -1 != ($pos = index $string, $sub, $pos+1); push @places, $pos)
#do nothing here

print "Locations of '$sub' in '$string' were: @places\n";

The compilation error was due to '–' instead of '-'; The inner loop was in fact a string literal (useless) plus comments (useless), the extra braces are useless as well.

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download