我正在使用Javascript解析一个中等复杂的语法,我想使用正则表达式匹配数字等标记。
给定一个包含语法的字符串,一个表示数字(例如)的正则表达式和字符串中的偏移量,我想知道正则表达式是否与该偏移量处的字符串完全匹配。
我可以设置lastIndex,调用RegExp.exec并检查结果匹配的index属性,看看匹配是否发生在预期的偏移量,但这是非常低效的,因为exec将搜索整个字符串,如果它找不到在起始偏移处匹配。
Javascript规范说“模式评估(”编译“)到内部过程值。然后,RegExp.prototype.exec可以将此过程应用于String和String中的偏移量,以确定模式是否匹配从正是字符串中的那个偏移。“
这正是我想要的,但似乎无法访问此内部功能。有谁知道是否有?
P.S。我目前通过将输入字符串拆分为一个标记数组来避免这个问题,但我不想这样做。
答案 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可以优化“任何字符的精确偏移时间”部分?