猿问

如何通过添加更多字符来知道字符串是否可以匹配正则表达式

这是一个棘手的问题,也许最终它没有解决方案(或者至少不是一个合理的解决方案)。我想要一个特定于 Java 的示例,但如果可以完成,我想我可以用任何示例来完成。


我的目标是找到一种方法来了解从输入流中读取的字符串是否仍然可以匹配给定的正则表达式模式。或者,换句话说,读取流直到我们得到一个绝对不匹配这种模式的字符串,无论你添加多少字符。


实现这一点的极简主义简单方法的声明可能是这样的:


boolean couldMatch(CharSequence charsSoFar, Pattern pattern);

这种方法会返回true的情况下charsSoFar,如果增加了新的人物还是能模式,或者false如果它有一点机会都没有与之相匹配的,甚至增加新的人物。


举一个更具体的例子,假设我们有一个像"^([+-]?\\d*\\.?\\d*)$".


使用这样的模式,couldMatch将返回true以下示例charsSoFar参数:


"+"  

"-"  

"123"  

".24"  

"-1.04" 

依此类推,因为您可以继续为所有这些添加数字,并在前三个数字中添加一个点。


另一方面,从前一个派生的所有这些示例都应该返回false:


"+A"  

"-B"  

"123z"  

".24."  

"-1.04+" 

乍一看很明显,无论您添加多少字符,这些都永远不会符合上述模式。


编辑:


我现在添加我当前的非正则表达式方法,以便使事情更清楚。


首先,我声明了以下功能接口:


public interface Matcher {

    /**

     * It will return the matching part of "source" if any.

     *

     * @param source

     * @return

     */

    CharSequence match(CharSequence source);

}

然后,之前的函数将被重新定义为:


boolean couldMatch(CharSequence charsSoFar, Matcher matcher);

浮点数的(起草的)匹配器可能看起来像(注意这在开始时不支持 + 号,只支持 -):


public class FloatMatcher implements Matcher {

    @Override

    public CharSequence match(CharSequence source) {

        StringBuilder rtn = new StringBuilder();


        if (source.length() == 0)

            return "";


        if ("0123456789-.".indexOf(source.charAt(0)) != -1 ) {

            rtn.append(source.charAt(0));

        }


        boolean gotDot = false;

        for (int i = 1; i < source.length(); i++) {

            if (gotDot) {

                if ("0123456789".indexOf(source.charAt(i)) != -1) {

                    rtn.append(source.charAt(i));

                } else

                    return rtn.toString();

            } else if (".0123456789".indexOf(source.charAt(i)) != -1) {

                rtn.append(source.charAt(i));

                if (source.charAt(i) == '.')

                    gotDot = true;

            } else {

                return rtn.toString();

            }

        }

        return rtn.toString();

    }

}

在 canMatch 方法的省略体中,它只会迭代调用 matcher.match() 并在源参数的末尾添加一个新字符,并在返回的 CharSequence 等于源参数时返回 true,并在返回时立即返回 false它是不同的(意味着添加的最后一个字符破坏了匹配)。


眼眸繁星
浏览 182回答 2
2回答

慕村225694

你可以很容易做到boolean couldMatch(CharSequence charsSoFar, Pattern pattern) {&nbsp; &nbsp; Matcher m = pattern.matcher(charsSoFar);&nbsp; &nbsp; return m.matches() || m.hitEnd();}如果序列不匹配并且引擎没有到达输入的末尾,则意味着在末尾之前存在一个矛盾的字符,在末尾添加更多字符时该字符不会消失。或者,正如文档所说:如果在此匹配器执行的最后一次匹配操作中搜索引擎命中了输入的结尾,则返回 true。当此方法返回 true 时,更多输入可能会更改上次搜索的结果。这也在Scanner类内部使用,以确定它是否应该从源流加载更多数据以进行匹配操作。将上述方法与您的样本数据一起使用会产生Pattern fpNumber = Pattern.compile("[+-]?\\d*\\.?\\d*");String[] positive = {"+", "-", "123", ".24", "-1.04" };String[] negative = { "+A", "-B", "123z", ".24.", "-1.04+" };for(String p: positive) {&nbsp; &nbsp; System.out.println("should accept more input: "+p&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; +", couldMatch: "+couldMatch(p, fpNumber));}for(String n: negative) {&nbsp; &nbsp; System.out.println("can never match at all: "+n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; +", couldMatch: "+couldMatch(n, fpNumber));}should accept more input: +, couldMatch: trueshould accept more input: -, couldMatch: trueshould accept more input: 123, couldMatch: trueshould accept more input: .24, couldMatch: trueshould accept more input: -1.04, couldMatch: truecan never match at all: +A, couldMatch: falsecan never match at all: -B, couldMatch: falsecan never match at all: 123z, couldMatch: falsecan never match at all: .24., couldMatch: falsecan never match at all: -1.04+, couldMatch: false当然,这并没有说明将不匹配的内容变成匹配的可能性。您仍然可以构建没有其他字符可以匹配的模式。但是,对于浮点数格式这样的普通用例,这是合理的。

沧海一幻觉

我没有具体的解决方案,但你可以用否定来做到这一点。如果您在黑名单中设置了与您的模式绝对不匹配的正则表达式模式(例如 + 后跟字符),您可以对照这些进行检查。如果列入黑名单的正则表达式返回 true,则可以中止。另一个想法是使用负前瞻(https://www.regular-expressions.info/lookaround.html)
随时随地看视频慕课网APP

相关分类

Java
我要回答