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

I know I am close, but I am running into trouble with special characters. I want to grab text from html and then do processing on it later. The trouble I am having is grabbing the text. I want to grab text between the following: <a name=" Of course the text in between is what I need and I understand that is grabbed by $1.
open (OUTPUT, ">>$output") or die "Cannot open $output"; if ($SFS =~ /<a name="([\s\S]+?)</a></big>) { $device = $1; }
Could someone please help me? Thanks, S

Replies are listed 'Best First'.
Re: How do I select text between two bits of text?
by GrandFather (Saint) on Dec 04, 2011 at 02:52 UTC

    If you are attempting to parse HTML then you'll probably save yourself a lot of time by using one of the HTML modules from CPAN. Depending on what you are trying to achieve, it may be that HTML::TreeBuilder will do the trick for you.

    If you are generating the HTML being parsed yourself then maybe it is sufficiently regular that you can get away with using simple regular expressions. But being able to parse wild HTML is a difficult task best left to long in the tooth modules with appropriate experience for the job.

    True laziness is hard work
      If you are attempting to parse HTML then you'll probably save yourself a lot of time by using one of the HTML modules from CPAN.
      You *might* save time. Or you might waste a bunch of time (1) figuring out which of a multitude of modules suits you; (2) learning your chosen module's horrible, baroque API; (3) realizing that your HTML is too lax (or invalid) for your chosen module to parse. If it's machine-generated and you just want to pull out something simple, stick with your regex.

        As the sig says "True laziness is hard work". Often the hardest part is figuring out the laziest option. In the context of parsing HTML, and especially if it's not a one off, learning one of those nasty APIs is by far the laziest option.

        True laziness is hard work
Re: How do I select text between two bits of text?
by davido (Cardinal) on Dec 04, 2011 at 02:36 UTC

    What are the single-quotes for? I see them in your regexp, but don't see them in the text you said you're trying to match against. Also, since you didn't actually mention it, are we supposed to assume that the match is failing?

    One issue you have is that the / character is being used as your regexp delimiter, and also as part of your pattern. Better to select a different regexp delimiter, as in, m{ ...... } instead of m/ ....... /

    It would have helped if you had posted code that compiles so we could focus on what's happening incorrectly rather than being distracted by wondering whether compilation errors are the root of your question.


    Dave

Re: How do I select text between two bits of text?
by ww (Archbishop) on Dec 04, 2011 at 03:19 UTC
    While agreeing with GrandFather on the wisdom of using tried-and-true Modules in the HTML family, and seconding davido's objections to your code, if your use of the <a name=... construct satisfies the HTML 4.01 standard, this should work:
    #!/usr/bin/perl use Modern::Perl; my $capture; my $SFS = '<big><a name="hit men for hire" style="font-weight:bold;">H +it Men</a></big>'; # *1 my $regex = qr#<a name="([^"]+)#; # *2 if ( $SFS =~ /$regex/ ) { $capture = $1; say "\$capture: $capture" }else { say "No match"; } # $capture: hit men for hire

    *1: Use of a style or span tag, among others, is legit... and a complication for which you'll want to allow unless you can be absolutely positive from now till the heat death of the universe, that no such element will appear in the hmtl you're parsing.

    *2: The regex uses a negated character class which matches one or more of anything that is not a double-quote. The definitive end of the text *3 in an <a name="... element is the closing quote which matchs the opening quote. It may be single or double, but must match. So use that fact in your regex; write your regex specifying ONLY the minimum required to satisfy your spec; anything extra is just an invitation to error.

    *3: The style component of the tag is, of course, text, but within what I understand to be the common meaning in OP's context, only the quoted portion is "text;" the style component is not what being described.

    For a better understanding of regexen, see the relevant section in Tutorials, perlretut and similar.

      Use of a style or span tag, among others, is legit... and a complication for which you'll want to allow unless you can be absolutely positive from now till the heat death of the universe, that no such element will appear in the hmtl you're parsing.
      I strongly disagree with the sentiment. By all means, if you're paying for your own time, feel free to make the effort to write extremely defensive code, that will last forever.

      Often though, it makes less sense. See, every minute you spend coding for something that may happen between now and the end of the universe, is a wasted minute if said thing never happens, or it doesn't happen until the program is obsoleted. A minute you could have spend writing something that actual scratches a current itch, solves a problem that needs fixing now, or something that will make money right now.

      In this case, I don't think we'll be generating or parsing HTML 4.01 a few decades from now; 75% will be "tag soup, but at least it works on IE 6", 20.9% will work on the designers setup, and only on the designers setup, 4% will not work anywhere, nor does it follow any known standard, and the remaining 0.1% has made an attempt to follow a newer standard.

      That having said, it may (or may not) make sense for the OP to cater for such an element appearing in the HTML text. But without knowing more about the context, I can't say for sure.

Re: How do I select text between two bits of text?
by vinian (Beadle) on Dec 04, 2011 at 07:13 UTC

    1. since '/' appears in the match string, you shoule use some other delimiters make it easy to read, such as m{...};
    2. your regex didn't end, i only see the triple '/', it should be four in there.
    I think you can try this regex
    $SFS =~ m{<a name="([^"]+?)</a></big>}
    Meanwhile, cpan can ease you work, follow GrandFather 's advice

Re: How do I select text between two bits of text?
by TJPride (Pilgrim) on Dec 04, 2011 at 12:34 UTC
    I'm guessing he's manually parsing a page where the format is known, so he can extract information, and this isn't going to be a long-term thing that runs automatically. Therefore, a simple regex should do fine.

    For multiple matches:

    use strict; use warnings; my ($SFS, $device); $SFS = join '', <DATA>; while ($SFS =~ m|<a name="(.*?)"|sg) { $device = $1; print "$device\n"; } __DATA__ <a name="alpha"></a> <a name="bravo"></a> <a name="charlie"></a>

    To the OP: It's generally better practice to give us a sample of the input data (in this case, the HTML page) so we can be sure to give you exactly what you need.