Javascript RegExp是否可以在不搜索的情况下匹配精确的字符串偏移量?

Can a Javascript RegExp match at an exact string offset without searching?

本文关键字:字符串 偏移量 情况下 Javascript 是否 搜索 RegExp      更新时间:2023-09-26

我正在使用Javascript解析一个中等复杂的语法,我想使用正则表达式来匹配标记,如数字。

给定一个包含语法的字符串,一个表示数字(例如)的正则表达式和字符串中的偏移量,我想找出正则表达式是否与该偏移量处的字符串完全匹配。

我可以设置lastIndex,调用RegExp。执行并检查结果匹配的index属性,看看匹配是否发生在预期的偏移量处,但这是非常低效的,因为如果在开始偏移量处没有找到匹配,Exec将搜索整个字符串。

Javascript规范说"一个模式计算("编译")到一个内部过程值。"然后,RegExp.prototype.exec可以将此过程应用于String和String中的偏移量,以确定模式是否将从String中的偏移量开始匹配。"

这正是我想要的,但是似乎没有办法访问这个内部函数。有人知道有吗?

注:我目前通过将输入字符串拆分为一个令牌数组来避免此问题,但我不希望这样做。

我已经彻底测试了可能有效的方法,参见JSPerf: ~20000 charars, ~1000000 charars。我创建了一个函数来生成由字母数字字符组成的随机字符串。运行此函数一次后,将创建一个RegExp模式,在给定的偏移量处匹配长度为10的字符串。

测试用例(当if(..)中的条件为真时,模式在偏移量index处找到):

var string = "...about 20000 characters: A-Z a-z 0-9...";
var regexp = /abcdef1324/g;
var regexpSubstr = /^abcdefg1234/;
var index = 10000;
/*1*/ if ( regexpSubstr.exec(string.substr(index,10)) ) ;
/*2*/ regexp.lastIndex = index;
      var found =  regexp.exec(string);
      if (found && found.length + index == regexp.lastIndex ) ;
/*3*/ if ( regexpSubstr.test(string.substr(index,10)) ) ;
/*4*/ // Only when the RegExp matches a fixed number of characters
      regexp.lastIndex = index;
      if ( regexp.test(string) && regexp.lastIndex == index + 10 ) ;

Case 1Case 3是等价的,因为它们检查子字符串是否匹配/^abcdef1234/模式(所选子字符串是否以"abc..etc"开头)。

案例2案例4使用.lastIndex方法:
,,1. ,将RegExp的.lastIndex属性设置为所需的偏移量
,,2. ,检查是否找到模式。
,,3.,检查找到的模式是否位于偏移量index处。
这些方法需要正则表达式启用全局标志。

对于非常大的字符串,方法4 (lastIndex + test)被证明是最有效的,当在偏移位置发生匹配时。然而,方法4要求匹配的模式具有预定义的固定大小。

当匹配发生在给定位置时,方法3 (substr + test)略慢于方法4。但是,当在大字符串中没有找到匹配时,方法3明显比方法4快。当没有找到匹配项时,方法1和方法3似乎同样快。

RegExp methods
.exec似乎并不比.test更有效率。match方法不适用于这种情况,因为它尝试查找所有匹配项,而不考虑.lastIndex属性。另一个可能的RegExp函数是.search函数,与前面展示的方法相比,它对于大字符串要慢得多。

如果您可以设置搜索开始位置,您可能能够利用
在断言中终止一个真正不匹配的结束锚。

它要求你接受这样一个事实:它唯一不匹配的时候(在表面上)
当开始位置落在字符串的末尾时。

然后post process检查捕获缓冲区的长度。它取决于正则表达式
但是,如果捕获缓冲区的长度为零,则可能失败。

例子:
('d{6} | (?!$))( (?:any subexpression) | (?!$) )

this将始终匹配(除非起始位置在字符串的末尾,或者
)字符串为空)。

结果


—不匹配:字符串为空,或者起始位置在字符串的末尾。
—匹配率:%99.999。如果捕获缓冲区的长度为0(即:"),则
左侧的交替失败,或者通过不捕获任何东西通过,依赖于正则表达式。

开始位置被考虑,然而,正则表达式中的静态长度匹配有时很难(不是不可能)用量词来控制。它可能更
在开放式量词的情况下,对子字符串使用regex是合理的。

可能是new RegExp("^.{" + offset + "}whatever"),即任何字符准确偏移时间,然后是什么?需要基准测试,但人们希望RegExp能够优化"任意字符精确偏移时间"。部分?