If the parentheses are always balanced, you can use a recursion-based regex like
__[A-Z0-9_]+__(\((?:[^()]++|(?-1))*\))
may fail if there is an unbalanced amount of (
or )
inside strings, see this regex demo. In brief:
__[A-Z0-9_]+__
- __
, one or more uppercase letters, digits or _
and then __
(\((?:[^()]++|(?-1))*\))
- Group 1: (
, then any zero or more occurrences of one or more chars other than (
and )
or the whole Group 1 pattern recursed, and then a )
(so the (...)
substring with any amount of paired nested parentheses is matched).
If you need to support unbalanced parentheses, it is safer to use a regex that just matches all allowed data formats, e.g.
__[A-Z0-9_]+__\(\s*(?:'[^']*'|\d+)(?:\s*,\s*(?:'[^']*'|\d+))*\s*\)
See the regex demo. Or, if '
can be escaped with a \
char inside the '...'
strings, you can use
__[A-Z0-9_]+__\(\s*(?:'[^'\\]*(?:\\.[^'\\]*)*'|\d+)(?:\s*,\s*(?:'[^'\\]*(?:\\.[^'\\]*)*'|\d+))*\s*\)
See this regex demo.
Details:
__[A-Z0-9_]+__
- __
, one or more upper or digits and then __
\(
- (
char
\s*
- zero or more whitespaces
(?:'[^']*'|\d+)
- '
, zero or more non-'
and then a '
or one or more digits
(?:\s*,\s*(?:'[^']*'|\d+))*
- zero or more occurrences of a ,
enclosed with optional whitespace and then either a '...'
substring or one or more digits
\s*\)
- zero or more whitespace and then a )
.
Note if you need to support any kind of numbers, you need to replace \d+
with a more sophisticated pattern like [+-]?\d+(?:\.\d+)?
or more.