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

Efficient string parsing in JS: How to create a substring which does not allocate a new string

本文关键字:字符串 创建 分配 高效 JS 何创建      更新时间:2023-09-26

我有大消息通过websocket,我想用正则表达式解析(为了简单)。

正则表达式识别报头的格式,在读取长度字段后,我们就知道下一个片段在哪里,然后我可以在该部分上运行正则表达式。

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

我想知道是否有任何正则表达式相关的函数允许我指定索引开始运行正则表达式?execsearch不允许我这样做。

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

关于这个有一个讨论:http://esdiscuss.org/topic/proposal-for-exact-matching-and-matching-at-a-position-in-regexp

我忘记了RegExp.prototype.exec为您处理这个,所以您只需继续传递原始字符串,它只会从最后停止的地方开始搜索。

这对我来说并不完全理想,因为它做了一大堆额外的解析,而不是我需要它(它将解析整个片段的内容),虽然。我想我可以把lastIndex向前推进。

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

因此,您的代码可能看起来像这样:
var re = /header:…length:('d+)/g;
for (var m; m=re.exec(re); ) {
    var len = parseInt(m[1], 10);
    re.lastIndex += len;
    …
}