Beefy Boxes and Bandwidth Generously Provided by pair Networks
"be consistent"
 
PerlMonks  

Re^2: Perl & regex help

by Kenosis (Priest)
on Jan 30, 2013 at 22:52 UTC ( #1016170=note: print w/ replies, xml ) Need Help??


in reply to Re: Perl & regex help
in thread Perl & regex help

Ah, yes. Perhaps a more general form for the html entities, e.g.,:

/&(?!.+?;)/

Update: I have no idea what I was 'thinking' here. Excellent and appreciated corrections to this below...


Comment on Re^2: Perl & regex help
Download Code
Re^3: Perl & regex help
by trizen (Friar) on Jan 30, 2013 at 23:33 UTC
    It fails on a string like this: "I saw a dog & a cat;".

    A safer solution, would be: /&(?!#?[a-zA-Z0-9]+;)/

      Excellent catch! Perhaps just the following: /&(?!\S+?;)/

      .
Re^3: Perl & regex help
by smls (Friar) on Jan 30, 2013 at 23:53 UTC

    That won't just exclude HTML entities from being matched, it will exclude any & character that is in the same line as a semicolon somewhere to the right of it, because .+? also matches whitespace.

    Instead, you should match for HTML/XML entities specifically. There are three forms that they can take, and the corresponding regexes for matching them would be:

      /&#[0-9]+;/ - character referenced by decimal number

      /&#x[0-9a-f]+;/i - character referenced by hexadecimal number

      /&[a-z]+;/i - character referenced by name

    Putting it together, you get this regex for matching an HTML entity:
      /&(?:#(?:[0-9]+|x[0-9a-f]+)|[a-z]+);/i

    Although that's kinda messy and pedantic, and you can probably get away with using this simplified version:
      /&#?[0-9a-z]+;/i
    (Unlike the more pedantic version, it would match some false positives such as &#amp; or &1a2b3c;, but what are the chances such constructs will appear in the input document?)

    To do what the OP requested, wrap everything after the & in a negative look-ahead bracket like choroba suggested:

    # 10 20 30 40 50 # ---------'---------'---------'---------'---------'---- my $str = "& ... & ... & ... &no_entity; ... & ... ;"; while ($str =~ /&(?!#?[0-9a-z]+;)/gi) { print "Found ampersand at position ".pos($str)."\n"; }

    Output:

    Found ampersand at position 32 Found ampersand at position 48

    (i.e. it only matches the last two & characters in $str)

      I think your regex is the best, as it clearly aligns with the ISO specs. Nice work.

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: note [id://1016170]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others surveying the Monastery: (6)
As of 2014-08-20 23:33 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    The best computer themed movie is:











    Results (125 votes), past polls