4

I have two inputs reading into my command prompt, the first being a series of words that are to be searched by the program I'm writing, and the second being the file that contains where the words are to be found. So, for instance, my command prompt reads perl WebScan.pl word WebPage000.htm

Now, I have no trouble accessing either of these inputs for printing, but I am having great difficulty accessing the contents of the webpage so I can perform regular expressions to remove html tags and access the content. I realize that there is a subroutine available to do this without regular expressions that is far more effective, but I need to do with with regular expressions :(.

I can access the html file for printing with no trouble:

open (DATA, $ARGV[1]);
my @file = <DATA>;
print @file;

Which prints the entire code of the html page, but I am unable to pass regular expressions in order to remove html blocks. I keep receiving an error that says "Can't modify array dereference in s/// near," which is where I have my specific regular expression. I'm not sure how to get around this- I've tried converting the array into a scalar but then I am unable to access any of the data in the html at all (and no, it doesn't just print the number of values in the array :P)

How do I access the array's contents so I can use regular expressions to refine the desired output?

3
  • we need to see the regex code. Commented Jan 29, 2011 at 3:34
  • @codaddict => you get that error from something like perl -e '@array =~ s/.//' where perl bails out since the value returned by an array in scalar context is read only Commented Jan 29, 2011 at 3:48
  • 2
    Don't use DATA as a filehandle name, it is a special filehandle. Actually, don't use global file handles, use lexical filehandles. Use the 3 argument form of open to make them. open my $fh, '<', $ARGV[1] or die "Can't open $ARGV[1]: $!\n"; Commented Jan 29, 2011 at 4:32

1 Answer 1

15

It sounds like you are doing something like @file =~ s/find/replace/;. You are getting that error because the left hand side of the regex binding operator imposes scalar context on its argument. An array in scalar context returns its length, but this value is read only. So when your substitution tries to perform the replacement, kaboom.

In order to process all of the lines of the file, you could use a foreach loop:

foreach my $line (@file) {$line =~ s/find/replace/}

or more succinctly as:

s/find/replace/ for @file;

However, if you are running regular expressions on an HTML file, chances are you will need them to match across multiple lines. What you are doing above is reading the entire file in, and storing each line as an element of @file. If you use one of Perl's iterative control structures on the array, you will not be able to match multiple lines. So you should instead read the file into a single scalar. You can then use $file =~ s/// as expected.

You can slurp the file into a single variable by temporarily clearing the input record separator $/:

my $file = do {local $/; <DATA>};

In general, regular expressions are the wrong tool for parsing HTML, but it sounds like this is a homework assignment, so in that case its just practice anyway.

And finally, in modern Perl, you should use the three argument form of open with a lexical file handle and error checking:

open my $DATA, '<', $ARGV[1] or die "open error: $!";

my $file = do {local $/; <$DATA>};
Sign up to request clarification or add additional context in comments.

2 Comments

Awesome, thank you so much. Yes, this is a homework question, but unfortunately, neither the professor, not the TA, were kind enough to explain how to access the html file.
As an alternative for slurp (especially if you need to download that page first, but works for local pages too), you can use LWP::UserAgent, use LWP::UserAgent; my $ua = LWP::UserAgent->new(); my $html = $ua->get($address)->as_string(); Now you have the HTML source of the site named $address in the scalar $html.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.