正则表达式匹配不在字符串或正则表达式文本中的 JS 源

Regex matching JS source that's not in a string or regex literal

本文关键字:正则表达式 JS 文本 字符串      更新时间:2023-09-26

是否存在全面的正则表达式,当应用于 JavaScript 源代码时,将匹配所有有效的字符串文字(如 "say '"Hello'"")和正则表达式文字(如/and'/or/)?表达式必须涵盖所有边缘情况,包括换行符和转义序列。

或者,有谁知道用于匹配字符串和正则表达式文本之外的模式的正则表达式?

我的目标是实现一个简单的 JavaScript 语法扩展,允许在 delimeter 中使用宏(例如 {{@foo.bar}}#@foo.bar#)由预处理器扩展。但是,我希望宏仅在文字之外处理。

现在,我正在尝试仅使用字符串替换来实现这一点,而不必增强现有的JavaScript词法分析器/解析器。

这个 JavaScript 预处理器本身将在 JavaScript 中实现。

这是我用来匹配带引号字符串的正则表达式,这非常好,因为它应该适用于几乎所有引擎,因为它不需要回溯或回溯引用或任何巫毒教。这将匹配所有文本 INSIDE 文字。

"(''.|[^"])*"

根据引擎的不同,它可能支持非捕获组。在这种情况下,您可以使用

"(?:''.|[^"])*"

而且应该更快。

我认为这对正则表达式来说太多了。

考虑var foo = "//" // /"(?:''.|[^"])*"/ .字符串、注释和正则表达式文本在哪里开始和结束?您需要编写一个完整的 JavaScript 解析器来涵盖所有边缘情况。当然,解析器将使用正则表达式...

我可能会做类似的事情。不过,在某些可能的情况下,它需要改进。

var str = '"aaa '"sss ''t bbb" sss #3 ss# ((t sdsds)) ff ';
str += '/gg sdfd '/dsds/ {aaa bbb} {{ss}} {#sdsd#}';
var repeating = ['"','''''','/','''~','''#'];
// "example" 'example' /example/ ~example~ #example#
var enclosing = [];
enclosing.push(['''{','''}']);
enclosing.push(['''{''{','''}''}']);
enclosing.push(['''[',''']']);
enclosing.push(['''(''(',''')'')']);
// {example} {{example}} [example] ((example))
for (var forEnclosing='',i = 0 ; i < enclosing.length; i++) {
    var e = enclosing[i];
    var r = e[0]+'(''''['+e[0]+e[1]+']|[^'+e[0]+e[1]+'])*'+e[1];
    forEnclosing += r + (i < enclosing.length-1 ? '|' : '');
}
for (var forRepeating='',i = 0; i < repeating.length; i++) {
    var e = repeating[i];
    var r = e+'('''+e+'|[^'+e+'])*'+e;
    forRepeating += r + (i < repeating.length-1 ? '|' : '');
}
var rx = new RegExp('('+forEnclosing+'|'+forRepeating+')','g');
var m = str.match(rx);
try { for (var i = 0; i < m.length; i++) console.log(m[i]) }
catch(e) {}

输出:

"aaa "sss 't bbb"
#3 ss#
((t sdsds))
/gg sdfd /dsds/
{aaa bbb}
{{ss}}
{#sdsd#}

您可以使用正则表达式获得的最接近的是拥有一个与字符串文字(单引号或双引号)或正则表达式或注释(或其他可能包含虚假匹配项的内容)或宏对象之一匹配的正则表达式:

"[^"'']*(?:''.[^"'']*)*"
|
'[^''']*(?:''.[^''']*)*'
|
/[^/'']*(?:''.[^/'']*)*/[gim]*
|
/'*[^*]*(?:'*(?!/)[^*]*)*'*/
|
#@('w+'.'w+)#

如果组 #1 在比赛后包含任何内容,它一定是您要查找的内容。 否则,请忽略此匹配并继续下一场比赛。