Beefy Boxes and Bandwidth Generously Provided by pair Networks
Just another Perl shrine
 
PerlMonks  

Matching quote characters?

by Anonymous Monk
on Aug 05, 2006 at 14:01 UTC ( [id://565797]=perlquestion: print w/replies, xml ) Need Help??

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

Is there an elegant way (one expression) to match an opening quote character followed by some characters and an optional trailing quote character? I tried this:
my $string = '"foo"'; $string =~ s/\"(.*?)\"?/$1/; print $string;
But the .*? always gobbles up the trailing " and the \"? never matches it. I thought non-gready .* matched as few non-newline characters as possible. Why is it matching the final " if it could leave it for "? and the pattern would still match?

Replies are listed 'Best First'.
Re: Matching quote characters?
by liverpole (Monsignor) on Aug 05, 2006 at 15:31 UTC

        Why is it matching the final " if it could leave it for "? and the pattern would still match?

    In the greedy case, it's because that's how regexes work; if .* can match the quote ("), it will.  Note that it would be different if the trailing quote was non-optional; then the greedy match would only match up to but not including the final quote.

    In the non-greedy case, of course, it's the same problem; the non-greedy succeeds by matching nothing at all, as the optional final quote does not have to be matched either.

    Here's another way to look at the effect of a "non-optional" final quote for both the greedy and non-greedy cases:

    $string =~ s/\"(.*)\"/$1/; # <= Final quote " pushes left against # otherwise greedy match (.*) $string =~ s/\"(.*?)\"/$1/; # => Final quote " pulls right against # otherwise non-greedy match (.*?)

    So when the final quote is optional, neither of the above constraints get enforced; the greedy match can be maximally greedy, and the non-greedy match can be minimally greedy.

    And by the way, you don't need to escape the quotes in a regex.  \" can be just ".


    s''(q.S:$/9=(T1';s;(..)(..);$..=substr+crypt($1,$2),2,3;eg;print$..$/
Re: Matching quote characters?
by Leviathan (Scribe) on Aug 05, 2006 at 14:13 UTC

    Tell it not to match "

    $string =~ s/"([^"]+)"?/$1/;

    Update: after I posted, I realised that if you don't care for the closing quote, then you can simply remove all quotes:

    $string =~ s/"//g;
    --
    Leviathan.
Re: Matching quote characters?
by betterworld (Curate) on Aug 05, 2006 at 19:19 UTC
    my $string = '"foo"'; $string =~ s/\"(.*?)\"?/$1/; print $string;
    But the .*? always gobbles up the trailing "
    Actually it doesn't. Your non-greedy .*? matches as few characters as possible: Zero. Then, one or zero " follows. You can see it from the following snippet:
    my $string = '"foo"'; $string =~ s/"(.*?)"?/_$1_/; # note that you don't have to escape " print $string; # prints __foo"
    For a solution to your problem, see the other posts.
Re: Matching quote characters?
by rodion (Chaplain) on Aug 05, 2006 at 14:25 UTC
    try
    my $string = '"foo"'; my $string2 = '"foo'; $string =~ s/\"(.*?)\"|\"(.*?)/$1$2/; $string2 =~ s/\"(.*?)\"|\"(.*?)/$1$2/; print "$string -- $string2\n";
    I think in the $string =~ s/\"(.*?)\"?/$1/; version both the .*? and the \"? are non-gready, so it's a question of which one is less gready competing, and \"? wins becuas it's non -greedy.

    Updated:Corrected my muddle-headedness about "non-greedy ", thanks to betterwold.

      I think in the $string =~ s/\"(.*?)\"?/$1/; version both the .*? and the \"? are non-gready
      No, \"? is greedy. \"?? would be non-greedy.
Re: Matching quote characters?
by TedPride (Priest) on Aug 06, 2006 at 22:02 UTC
    The object is to get the shortest possible string that starts with " and ends with either " or the end of the sample. So:
    while (<DATA>) { chomp; print "$1\n" while m/(".*?(?:"|$))/g; } __DATA__ abc "def "ghi" jkl" mno"pqr"stu v"wx"y"z"

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://565797]
Approved by Tanktalus
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others chilling in the Monastery: (3)
As of 2024-04-25 23:45 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found