[EMAIL PROTECTED] <[EMAIL PROTECTED]> wrote:
> Please help!!!  I'm trying to complete an assignment to determine the number 
> of HTML tags within a string at each level of nesting.  ie:  for the string 
> 
> "<p><strong>a</strong><a>b</a></p><strong>c<italic>d<a>e</a></italic></strong>"
> 
> <p> is at level 0
> <strong> and <a> are at level 1
> etc...
> 
> My code is below.  The problem is that apparently my RegEx is wrong (in the 
> while loop), and so the loop is infinite, and no values are printed--just "".  
> I'm just learning perl, and RegEx is really confusing to me.  Any feedback 
> would be appreciated!

Okay -- first of all, be patient.  You mailed this three times.

> #!usr/bin/perl
> #Exercise 8.9
> #To determine how many HTML tags are included in a string at each level of nesting.
> 
> use strict;
> use warnings;
> 
> my $string = 
>"<p><strong>a</strong><a>b</a></p><strong>c<italic>d<a>e</a></italic></strong>";
> 
> print("The HTML string is:\n$string\n\n");
> 
> our @counter;
> count($string, 0);
> 
> for (0 .. $#counter){
>   print("There are $counter[$_] valid level",$_," html tags.\n");
> }
> 
> sub count
> {
>   my $string = shift();
>   my $level = shift();
> 
>   while ($string =~ m!.*?<([a-z]*?)>(.*)</\1>!g){

The regex is not bad, given that sample input.

There are two bugs and some unnecesary clutter, though:

  m!
    .*?          # This doesn't do anything useful.

                 # Since there's no anchor at the front, there's 
                 # no need to match the text in between <tags>.  
                 # Just let perl skip them.


    <([a-z]*?)>  # Here you don't need the "?".

                 # Since '>' is outside the range [a-z], the star 
                 # has to consume all the letters, and greediness
                 # can't enter into it.

                 # But you ought to consider whether you really 
                 # want to accept *zero* or more letters here.


    (.*)         # And _this_ might be a good place to use the 
                 # nongreedy "*?" quantifier.

    </\1> 

  !xg;

> #should remember html tag as 1 and contents as 2
>     $counter[$level]++;
>     print("Tag is \"\1\", contains \"\2\" ");

Backreferences (\1, \2, etc) are only valid inside the regex, where 
you've used \1 correctly.

Outside the regex, the captured substrings are in the digit variables
$1, $2 ... $n.

>     print("at level $level\n");
>     count($string, $level+1);
>
> #recursively calling count with the string and the level increased by one

Here you recursively process the original $string, which matches at the
same place and recurses again on the original $string, which matches at
the same place and... 

You want to recurse on "the bit in the middle", which was captured in the
second set of parens.

>   }
> }
> 

Since it's homework, I'll leave you to it.

But I really hope your instructor has explained that the only time 
you should use regexes on HTML is in the context of an exercise.

In real-life, go directly to HTML::Parser.

In fact, I'm probably assuming too much and you should go get 
HTML::Parser *right now* :)

-- 
Steve

perldoc -qa.j | perl -lpe '($_)=m("(.*)")'

-- 
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to