21 20 15 19 bytes
Try it here.
This matches a character (or the beginning of the input) before the beginning double quote and then reset the match, to make sure the double quote isn't shared with another match.
25 23 bytes
Thanks to Martin Büttner for golfing off 2 bytes.
Try it here.
\\.|[^"] # An escaped character, or a character that isn't a double quote
)*+ # Possessive zero-or-more quantifier, which means backtracking
# could not happen after first match is found. That means if \\.
# matched, it would never switch to [^"], because it is always a
# match if it just stopped after the \\. without backtracking.
(?!"(?R)|$) # Make sure it is not followed by a double quote and another
# match, or the end of the input.
Note that the possessive quantifier (
*+) made sure the negative lookahead always begins after a whole string, or a whole segment of non-string.
There are 4 cases:
- The match begins anywhere outside of a string.
\\. would never match a double quote according to the clarification. It could only end just before the next double quote which begins a string, or the end of input. Both cases fails the negative lookahead.
- The match begins at the beginning of a string.
(\\.|[^"])*+ would match a complete string. The next character must be a double quote, and couldn't be the end of input. After the double quote it is outside of the string, so it couldn't be another match. So it passes the negative lookahead.
- The match begins at the end of a string. It matches an empty string in the same way as the previous case. But it doesn't matter according to the clarification.
- The match begins in the middle of a string. Impossible because matches don't overlap.