Regex: match double OR single quote

Discussion in 'Perl Misc' started by Jason C, Jul 12, 2012.

  1. Jason C

    Jason C Guest

    I'm struggling with what I thought was a simple thing, and I'm hoping you guys can help.

    I have a string that may contain a ", ', or neither. So, I wrote this in the regex:

    ["|']*

    But this doesn't match anything.

    Here's the complete code:

    # $text comes from a form, so this is just a sample
    $text = <<EOF;
    <img src="<a href='http://www.example.com/whatever.jpg'
    target='_new'>
    http://www.example.com/whatever.jpg</a>"
    width="300" height="300" border="0">
    EOF

    # Regex; line breaks added here for the sake of reading
    $text =~ s/<img(.*?)src=
    ["|']*\s*<a.*? href=
    ["|']*\s*(.*?)
    ["|']*.*?>(.*?)<\/a>
    ["|']*(.*?)>
    /<img src="$2"$1$4>/gsi;

    If I change ["|']* to whatever I have hard coded, then it works fine, so I know the issue is with that pattern. So how do I correctly match them?
    Jason C, Jul 12, 2012
    #1
    1. Advertising

  2. Jason C

    Jason C Guest

    On Thursday, July 12, 2012 7:46:04 PM UTC-4, Ben Morrow wrote:
    <snip>
    > In general, .*? is not a panacea in situations like this. You would
    > probably be better off using negated character classes, something like
    >
    > $text =~ s{
    > &lt;img ([^&gt;]*) src=[&quot;'] \s*
    > &lt;a [^&gt;]* [ ] href=[&quot;'] \s* ([^'&quot;]*) [&quot;'] [^&gt;]* &gt;
    > ([^&lt;]*) &lt;/a&gt;
    > ['&quot;] ([^&gt;]*) &gt;
    > }{&lt;img src=&quot;$2&quot;$1$4&gt;}gsix;
    >
    > (I've used /x to format it decently, which means the literal space needs
    > to be escaped somehow. I usually prefer putting it in a character class
    > to backslashing it, though either would work.)
    >
    > Here each negated character class stops the match running off past the
    > next thing, so for instance $2 can't run past the end of the quotes.
    > This isn't perfect: it will not match at all if there are other tags
    > inside the &lt;a&gt;, and it's not terribly easy to modify it so it will.
    > (While it is possible to correctly match arbitrary HTML with Perl
    > regexes, it isn't entirely straightforward.)
    >
    > Ben


    Perfect! I actually did mean for the " or ' to be optional, though (it's possible to have references without a quote), so I had to add the * back in, but the idea of negated characters was exactly what I needed.

    For the sake of my own knowledge, does the pattern:

    /img([^>])src/

    translate to "img, not followed by a >, and followed by src", or "img, followed by anything except a >, and followed by src"?
    Jason C, Jul 13, 2012
    #2
    1. Advertising

  3. Jason C

    ccc31807 Guest

    On Jul 12, 6:12 pm, Jason C <> wrote:
    > I'm struggling with what I thought was a simple thing, and I'm hoping youguys can help.
    >
    > I have a string that may contain a ", ', or neither. So, I wrote this in the regex:


    If you process CSV files, this can get real hairy. CSV files can
    contain one or more double quotes, one or more single quotes, pairs of
    double and/or single quotes, and commas embedded within quotation
    marks. The best help, and one that I strongly recommend to you, is to
    examine the Perl source for one or more of the CSV modules. The
    contain regular expressions for dis-entangling CSV strings, and trying
    to understand how they work will strengthen your RE chops.

    I normally follow two strategies when faced with this situation.
    First, is to replace all non-delimiting or non-qulaifying quotation
    marks with some unusual character that's unlikely to appear in the
    string, such as
    s/["']/#/g
    and then later, after I've processed the string, reverse the change
    like this
    s\s/#/'/g
    which converts all the quotations to single quotes, which may or may
    not work for you (it normally works for me).

    Or, I escape the quotations with either single or double backslashes,
    depending on whatever subsequent processing you plan to do, like this
    s/(["'])/\$1/g
    This has the advantage of preserving the kinds of quotes.

    I'm posting from memory so the above might have errors, but you
    understand the idea.

    In practice, I find that single quotes turn up in the oddest places,
    where you would never expect them. For this reason, when I process a
    string, out of pure defensiveness, I usually escape quotes (as well as
    some other potentially trouble makers).

    CC
    ccc31807, Jul 16, 2012
    #3
  4. Jason C

    Jason C Guest

    On Friday, July 13, 2012 5:49:03 AM UTC-4, Ben Morrow wrote:
    > &gt; &gt; $text =~ s{
    > &gt; &gt; &amp;lt;img ([^&amp;gt;]*) src=[&amp;quot;&amp;#39;] \s*
    > ^^^^ ^^^^ ^^^^^^^^^^^
    > If you're going to be posting to programming newsgroups you need to find
    > a way to stop that from happening. Dropping Google in favour of a real
    > newsreader might be a good start.


    Blech, why did Google start doing that?? I really don't use NG's that often, but those substitutions sure make it hard to talk about regex!

    I guess I'll have to grab a copy of Forte Agent or something...


    > 'Optional' is ?, not *. Presumably you don't want to allow


    Maybe I really am confused. Regex isn't really my strong point, though, so I appreciate the clarification.

    I thought that ? made it not greedy; meaning, instead of catching the next reference, it would find the last reference.

    Example:

    $text = "Example >->->";
    $text = s/>?//;

    would return:

    Example ->->

    But this:

    $text = "Example >->->";
    $text = s/>//;

    would return:

    Example --

    Then, I thought that * meant "0 or more times", which would essentially make it optional?
    Jason C, Jul 18, 2012
    #4
  5. Ben Morrow <> writes:

    [...]

    >> Then, I thought that * meant "0 or more times", which would essentially
    >> make it optional?

    >
    > Well, yes, in a sense. 'Optional' is ambiguous; in this case, as I said,
    > I believe you want 0-or-1-times rather than 0-or-more-times.


    I don't think so. ? is equivalent to the quantifier {0,1}, * is
    equivalent to the quantifier {0,}. Both imply that the re they apply
    to is optional for success of the match (not matching it at all is
    fine). The difference is on the right side of the comma: The first one
    may match at most once, the second one represents an unbounded
    sequence.
    Rainer Weikusat, Jul 18, 2012
    #5
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Replies:
    3
    Views:
    13,151
  2. Eric Layman
    Replies:
    3
    Views:
    616
    Rad [Visual C# MVP]
    Apr 14, 2007
  3. Evan
    Replies:
    1
    Views:
    384
    Marc 'BlackJack' Rintsch
    Nov 4, 2008
  4. Evan
    Replies:
    3
    Views:
    506
    Marc 'BlackJack' Rintsch
    Nov 4, 2008
  5. vikrant
    Replies:
    8
    Views:
    349
    vikrant
    May 17, 2007
Loading...

Share This Page