'How do I match a pattern with optional surrounding quotes?

How would one write a regex that matches a pattern that can contain quotes, but if it does, must have matching quotes at the beginning and end?

"?(pattern)"?

Will not work because it will allow patterns that begin with a quote but don't end with one.

"(pattern)"|(pattern)

Will work, but is repetitive. Is there a better way to do that without repeating the pattern?



Solution 1:[1]

This is quite simple as well: (".+"|.+). Make sure the first match is with quotes and the second without.

Solution 2:[2]

Depending on the language you're using, you should be able to use backreferences. Something like this, say:

(["'])(pattern)\1|^(pattern)$

That way, you're requiring that either there are no quotes, or that the SAME quote is used on both ends.

Solution 3:[3]

This should work with recursive regex (which needs longer to get right). In the meantime: in Perl, you can build a self-modifying regex. I'll leave that as an academic example ;-)

my @stuff = ( '"pattern"', 'pattern', 'pattern"', '"pattern'  );

foreach (@stuff) {
   print "$_ OK\n" if /^
                        (")?
                        \w+
                        (??{defined $1 ? '"' : ''})
                       $
                      /x
}

Result:

"pattern" OK
pattern OK

Solution 4:[4]

Generally @Daniel Vandersluis response would work. However, some compilers do not recognize the optional group (") if it is empty, therefore they do not detect the back reference \1.

In order to avoid this problem a more robust solution would be:

/^("|)(pattern)\1$/

Then the compiler will always detect the first group. This expression can also be modified if there is some prefix in the expression and you want to capture it first:

/^(key)=("|)(value)\2$/

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Jonas Stensved
Solution 2 zigdon
Solution 3 rubber boots
Solution 4 marbri91