const regex = /\${(fn\.[a-zA-Z0-9\/._-]+)\( *((?:[a-zA-Z0-9\/._${}=, \"\'\[\]-]|(?R))*?) *\)}/gm;
// Alternative syntax using RegExp constructor
// const regex = new RegExp('\\${(fn\\.[a-zA-Z0-9\\\/._-]+)\\( *((?:[a-zA-Z0-9\\\/._${}=, \\"\\\'\\[\\]-]|(?R))*?) *\\)}', 'gm')
const str = `\${fn.abaco()}
\${fn.abaco(1)}
\${fn.abaco(2, 3)}
\${fn.abaco(2, 3)}
\${fn.abaco(\${config.a})}
\${fn.abaco\${config.t}(2, )}
\${fn.abaco(2, )}
anwkdfb a \${fn.abaco(\${config.a})} \${fn.aba\${fn.abaco(\${config.a})}co(\${config.a})} akwhcb kbkw bhj
\${fn.abaco(\${config.a}, \${fn.a()})}
\${fn.abaco(\${config.a}, \${fn.a}, [1, 2, 3])}
\${fn.aba\${fn.abaco(\${config.a})}co}
\${fn.aba\${fn.abaco(\${fn.a(})}co}
\${fn.identity( \${fn.identity(\${fn.identity(\${fn.identity(\${foo})})})} )}
\${fn.and( True, True )}
\${fn.and( \${config.first_part}, \${config.second_part} )}
\${fn.map( \${config.arg}, \${fn.lambda([x], \${fn.sum(\${L.x}, 1)})} )}
\${fn.map( elem=\${config.arg}, map_fn=\${fn.lambda([x], \${fn.sum(\${L.x}, 1)})} )}`;
// Reset `lastIndex` if this regex is defined globally
// regex.lastIndex = 0;
let m;
while ((m = regex.exec(str)) !== null) {
// This is necessary to avoid infinite loops with zero-width matches
if (m.index === regex.lastIndex) {
regex.lastIndex++;
}
// The result can be accessed through the `m`-variable.
m.forEach((match, groupIndex) => {
console.log(`Found match, group ${groupIndex}: ${match}`);
});
}
Please keep in mind that these code samples are automatically generated and are not guaranteed to work. If you find any syntax errors, feel free to submit a bug report. For a full regex reference for JavaScript, please visit: https://developer.mozilla.org/en/docs/Web/JavaScript/Guide/Regular_Expressions