2009-01-06 57 views
13

在Javascript中,我定义了一个正则表达式,现在用户正在键入一个字符串。我想告诉他,如果他的字符串仍然可以匹配RegExp,如果他继续打字或者他已经走错了路。例如:检查字符串是否是Javascript的前缀RegExp

var re = /a*b/; 

"a".isPrefixOf(re); // true 
"x".isPrefixOf(re); // false 

isPrefixOf的执行情况怎么样?

更新:感谢您的回答,正如Brad所建议的,正则表达式的前缀证明似乎是一个很好的解决方法。但我仍然试图找到一个通用的解决方案。

也许这样:我们创建一个新的正则表达式,用户输入后跟.*。这个正则表达式描述了用户仍然可以输入的所有单词。如果这个创建的正则表达式与原始正则表达式的交集是空的,那么用户已经走错了路。如果不是,他的表现很好。例如:

var re = /a*b/; 
var sInput = "a"; 
var reInput = new RegExp(sInput + ".*"); 

reIntersection = re.intersect(reInput); 
reIntersection.isEmpty(); // false 

intersect()返回只接受这两个rereInput将接受字一个新的正则表达式。该功能尚不存在,但我们可以用前瞻实现它:

RegExp.prototype.intersect = function(pattern2) { 
    return new RegExp('(?=' + this.source + ')' + pattern2.source); 
} 

剩下的开放是isEmpty()功能。我们如何检查,如果Javascript正则表达式匹配任何单词或者它是空的?

回答

-1

首先你定义你的正则表达式为: var re = new RegExp(/ ^(regexp here)$ /);

在onkeypress事件事件

,你检查这样的正则表达式:

text.match(正则表达式) - 在文字输入的字符串。

这是否清楚?

+1

你应该仔细阅读这个问题。它不会问如何调用匹配器。它询问如何编写匹配器。 – user51568 2009-01-06 14:03:47

-1

这样做的一种方法可能是挂钩到文本框的onKeyUp事件,并且.test针对正则表达式的文本。 我的假设当然是你想做正则表达式匹配。 我不知道这是否是你所需要的东西,其实你的代码:

"a".isPrefixOf(re); // true 

永远不会匹配,因为它需要也有一个后续的“B”字(可能要修改规则表达)。 例如,这段代码测试对任何字符串匹配以下格式:

a-n(n)-b 

下面是代码,将其保存为一个网页,并在浏览器中加载它:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="it"> 
<body> 
    <input type="text" size="20" id="txtData" onkeyup="showResult()" /> 
    <div id="dvResult" /> 
</body> 
</html> 
<script type="text/javascript"> 
//<![CDATA[ 

    theRegExp = /^a\-\d{1,2}\-b$/; 

    function isPrefixOf(aText, aRegExp) 
    { 
     return aRegExp.test(aText); 
    } 

    function showResult() 
    { 
     res = document.getElementById("dvResult"); 
     res.innerHTML = isPrefixOf(document.getElementById("txtData").value, theRegExp) ? "Correct" : "Bad input"; 
    } 

//]]> 
</script> 
+0

你应该仔细阅读这个问题。它不会问如何调用匹配器。它询问如何编写匹配器。 – user51568 2009-01-06 14:04:59

+0

这就是为什么我用粗体文本突出显示该笔记! – Manuel 2009-01-06 15:12:24

+0

虽然问题本来可以更好地表达,但我认为这不难理解。你想让我删除什么投票? – user51568 2009-01-06 18:11:37

2

非常有趣的问题。在我的快速搜索中,我没有发现任何预定义的东西(即使在Perl中也没有)解决了这个问题。

编辑:哎呀,它似乎Java有类似的东西叫做hitEnd() - 见艾伦M的答案。 hitEnd()所做的就是说match()(无论是true还是false)的结果可能会被其他输入修改。“掌握正则表达式”这本书说这不是很可靠,但(不知道为什么,第392页不适用于谷歌的书籍)

根据你使用的正则表达式的特点,快速入侵像写一些类型的前缀你的正则表达式的:

例如,对于A + A * b + C的前缀是:。

 
a+ 
a+a* 
a+a*b+ 
a+a*b+c 

,并尝试以配合您的字符串可能工作的任何人这个快速破解变得困难,如果你如果使用范围运算符{n,m}或反向引用,则使用选择运算符。

这就是说,我认为最好的解决方案是略微修改匹配算法。

通常采用的匹配算法是回溯算法(即使最坏情况下的行为是指数型的,它在实践中仍然运行良好)。只要到达正则表达式的末尾,该算法就会成功终止(即使不是整个字符串已被使用)。你需要做的是修改终止条件,以便当它消耗了所有的输入时也终止成功。

这就是说,你可能不得不在JavaScript中实现算法。希望这将成为像Jquery这样的图书馆的一部分。

更多的参考和理论的算法,本文取出来:

http://swtch.com/~rsc/regexp/regexp1.html

(即使它使对回溯算法的情况下,并建议FA基于算法(但英足总无法处理反向引用))。

3

我认为你最好的选择是让你的Regex前缀证明。对于你给的例子,/a*b/,我想你可以使用/a*b?/.test(userinput)。对于更复杂的模式,这可能变得越来越困难,但我仍然认为可以通过将每个子表达式嵌套在一系列可选量词(?)中来完成。例如:

/a*bcd*e/ 

前缀正则表达式可能是:

/a*(b(c(d*e?)?)?)?/ 

它有点乱,但会解决你的问题相当好,我认为。

4

人们似乎正在分裂他们如何解释这个问题,所以我会用Java示例演示这个概念。

import java.util.regex.*; 

public class Test 
{ 

    public static void main(String[] args) throws Exception 
    { 
    tryMatch("^a*b+$", "a", "ab", "abc"); 
    } 

    public static void tryMatch(String regex, String... targets) 
    { 
    Pattern p = Pattern.compile(regex); 
    Matcher m = p.matcher(""); 
    System.out.printf("%nregex: %s%n", regex); 
    System.out.printf("target | matches() | hitEnd()%n"); 
    for (String str : targets) 
    { 
     m.reset(str); 
     System.out.printf("%-6s | %-9B | %-9B%n", 
      str, m.matches(), m.hitEnd()); 
    } 
    } 
} 

输出:

regex: ^a*b+$ 
target | matches() | hitEnd() 
a  | FALSE  | TRUE 
ab  | TRUE  | TRUE 
abc | FALSE  | FALSE 

目标字符串“a”不匹配,因为正则表达式至少需要一个b,但它可能是一个成功匹配的前缀,所以hitEnd()回报true。字符串“ab”具有匹配所需的全部内容,但如果我们在末尾添加更多b's,则匹配也会匹配,因此hitEnd()仍然会返回true。使用“abc”时,匹配尝试在到达目标字符串的末尾之前失败,因此正则表达式无法匹配任何以“abc”开头的字符串。

据我所知,Javascript没有像Java的hitEnd()方法,但它可能是假的。如果有人知道如何,那就是Flagrant Badass,Steven Levithan