Javascript RegExp可以匹配精确的字符串偏移量而无需搜索吗?

时间:2011-10-21 17:42:40

标签: javascript regex

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

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

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

Javascript规范说“模式评估(”编译“)到内部过程值。然后,RegExp.prototype.exec可以将此过程应用于String和String中的偏移量,以确定模式是否匹配从正是字符串中的那个偏移。“

这正是我想要的,但似乎无法访问此内部功能。有谁知道是否有?

P.S。我目前通过将输入字符串拆分为一个标记数组来避免这个问题,但我不想这样做。

3 个答案:

答案 0 :(得分:7)

我已经彻底测试了可能有效的方法,请参阅JSPerf: ~20000 字符, ~1000000 字符。我创建了一个函数来生成一个由字母数字字符组成的随机字符串。运行此函数一次后,将创建一个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 ) ;

案例1 案例3 是等效的,因为他们正在检查子字符串是否与/^abcdef1234/模式匹配(所选子字符串是否以“abc”开头) ..等“?)。

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

在非常大的字符串处,方法4(lastIndex + test)是proved to be most efficient,在偏移发生时匹配。但是,方法4要求匹配的模式具有预定义的固定大小。

当在给定位置发生匹配时,方法3(substr + test)略慢于4。但是,如果在大字符串中找不到匹配项,则方法3为significantly faster而不是方法4.当找不到匹配项时,方法1和方法3似乎为equally fast

RegExp方法
.exec似乎不比.test更有效率。 match方法不适合这种情况,因为无论.lastIndex属性如何,它都会尝试查找所有匹配项。另一个可能的RegExp函数是.search函数,与以前显示的方法相比,它对于大字符串来说要慢得多。

答案 1 :(得分:3)

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

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

然后发布进程以检查捕获缓冲区的长度。这取决于正则表达式,
但可能的失败是捕获缓冲区的长度为零。

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

这将始终匹配(除非起始位置位于字符串的末尾,或者是 字符串是空的。)


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

开始位置得到了处理,然而,正则表达式中的静态长度匹配有时很难(不是不可能)用量词来控制。它可能更多 在开放式量词的情况下,合理地在子串上使用正则表达式。

答案 2 :(得分:0)

也许是new RegExp("^.{" + offset + "}whatever"),即,任何字符正好偏移时间,后跟什么?需要进行基准测试,但是有人希望RegExp可以优化“任何字符的精确偏移时间”部分?