Why doesn't it work
You can't use a character class to match a character not preceded by another character. This is because a character class (negated or not) must still match a character. For example, [^a]b
does not mean "b
not preceded by a
". It means: "a character that's not a
followed by b
".
The Solution
If you want to match a single-quote or double-quote character not preceded by a backslash, then you'll have to use a lookaround expression (a negative lookbehind, specifically).
The regex you're looking for is (?<!\\\\)[\'"]
.
Autopsy:
(?<!
- start of the lookbehind expression\\\\
- match a literal backslash character
)
- end of the lookbehind expression[\'"]
- character class that matches a single character from the list"'
Visual Representation:
This effectively matches any single-quote / double-quote character that is not preceded by a literal backslash character.
Using the above expression with preg_match_all
is simple:
$subStr = 'asdf"asdf""a\\"sdf\'asdf\'\'a\\\'sdf';
preg_match_all('/(?<!\\\\)[\'"]/', $subStr, $matches);
echo count($matches[0]); // => 6