Javascript JS中高效的字符串解析:如何创建不分配新字符串的子字符串

Javascript JS中高效的字符串解析:如何创建不分配新字符串的子字符串,javascript,regex,Javascript,Regex,我想用正则表达式(为了简单起见)解析来自websocket的大量消息 正则表达式识别头的格式,读取长度字段后,我们就知道下一段的位置,我可以在该部分上运行正则表达式 然而,由于我的整个消息可能很大(比如说…10MB),并且由许多段组成(比如…1000,其中平均段长度略低于1K),然后天真地将主消息切分,将其传递回下一个位置的re.exec(),这似乎会导致大量GC抖动,如果不是,则仅为原始字符串内容分配千兆字节 我想知道是否有任何与regex相关的函数允许我指定开始运行regex的索引执行和搜索

我想用正则表达式(为了简单起见)解析来自websocket的大量消息

正则表达式识别头的格式,读取长度字段后,我们就知道下一段的位置,我可以在该部分上运行正则表达式

然而,由于我的整个消息可能很大(比如说…10MB),并且由许多段组成(比如…1000,其中平均段长度略低于1K),然后天真地将主消息切分,将其传递回下一个位置的
re.exec()
,这似乎会导致大量GC抖动,如果不是,则仅为原始字符串内容分配千兆字节


我想知道是否有任何与regex相关的函数允许我指定开始运行regex的索引<代码>执行和
搜索
不要让我这样做

我忘了,
RegExp.prototype.exec
会为您处理这个问题,所以您只需不断传入原始字符串,它只会从上次停止的位置开始搜索


不过,这对我来说并不理想,因为它需要进行大量额外的解析(它将解析整个片段的内容)。我想我可以“进入”并向前推动
lastIndex

是的,有一种方法,但不是通过函数的参数。相反,您可以利用RegExp对象的属性(需要设置全局标志)。
match
replace
exec
test
方法将尊重此值

因此,您的代码可能如下所示:

var re = /header:…length:(\d+)/g;
for (var m; m=re.exec(re); ) {
    var len = parseInt(m[1], 10);
    re.lastIndex += len;
    …
}
ES6在regexp上定义了一个“sticky”标志,该标志允许检查字符串是否在特定位置以regexp开头:

var position = 3;
var string = "la-la-la";

var re = /\d+/y;
re.lastIndex = position;
var match = re.exec(string);
//... do something with match
对此有一个讨论:

您可以在一个子字符串上运行正则表达式,从您想要使用的任何索引开始无效?为什么您认为创建子字符串会分配新内存?由于字符串在JS中是不可变的,因此可以在实现中轻松地对其进行优化。您是否有任何实际的性能问题?文档没有明确说明
子字符串是否创建了字符串的新实例,或者它是否能够引用原始字符串。然而,每一个其他子字符串方法都明确表示它创建了一个新字符串,而我绝对需要避免的那些方法JavaScript无法控制如何管理字符串值。虽然10MB的字符串可能超过浏览器允许的大小,但您可能希望研究使用类型化数组。您是否阅读了其他两个答案
lastIndex
存在并运行多年。还有,这是一个很长的讨论。@StevenLu:不过,粘性标志会使匹配更有效,因为正则表达式需要精确地(并且只)匹配
lastIndex
所说的应该匹配的地方,而今天,如果它不匹配,它会立即检查字符串的其余部分。这就像一个锚定匹配:
/^regex/.test(str.slice(n))
。我不能自己设置最后一个索引来完成吗?