验证String是否与格式String匹配

时间:2011-08-25 11:14:27

标签: java regex string string-formatting

在Java中,如何确定字符串是否与format string匹配(即:song%03d.mp3)?

换句话说,您将如何实现以下功能?

/**
* @return true if formatted equals String.format(format, something), false otherwise.
**/
boolean matches(String formatted, String format);

示例:

matches("hello world!", "hello %s!"); // true
matches("song001.mp3", "song%03d.mp3"); // true
matches("potato", "song%03d.mp3"); // false

也许有办法将格式字符串转换为正则表达式?

澄清

格式String是一个参数。我不提前知道。 song%03d.mp3只是一个例子。它可以是任何其他格式字符串。

如果有帮助,我可以假设格式字符串只有一个参数。

7 个答案:

答案 0 :(得分:9)

我不知道这样做的图书馆。以下是如何将格式模式转换为正则表达式的示例。请注意,Pattern.quote对于处理格式字符串中的意外正则表达非常重要。

// copied from java.util.Formatter
// %[argument_index$][flags][width][.precision][t]conversion
private static final String formatSpecifier
    = "%(\\d+\\$)?([-#+ 0,(\\<]*)?(\\d+)?(\\.\\d+)?([tT])?([a-zA-Z%])";

private static final Pattern formatToken = Pattern.compile(formatSpecifier);

public Pattern convert(final String format) {
    final StringBuilder regex = new StringBuilder();
    final Matcher matcher = formatToken.matcher(format);
    int lastIndex = 0;
    regex.append('^');
    while (matcher.find()) {
        regex.append(Pattern.quote(format.substring(lastIndex, matcher.start())));
        regex.append(convertToken(matcher.group(1), matcher.group(2), matcher.group(3), 
                                  matcher.group(4), matcher.group(5), matcher.group(6)));
        lastIndex = matcher.end();
    }
    regex.append(Pattern.quote(format.substring(lastIndex, format.length())));
    regex.append('$');
    return Pattern.compile(regex.toString());
}

当然,实施convertToken将是一项挑战。这是开始的事情:

private static String convertToken(String index, String flags, String width, String precision, String temporal, String conversion) {
    if (conversion.equals("s")) {
        return "[\\w\\d]*";
    } else if (conversion.equals("d")) {
        return "[\\d]{" + width + "}";
    }
    throw new IllegalArgumentException("%" + index + flags + width + precision + temporal + conversion);
}

答案 1 :(得分:1)

您可以使用Java正则表达式 - 请参阅http://www.vogella.de/articles/JavaRegularExpressions/article.html

...谢谢

答案 2 :(得分:1)

由于您事先不知道格式,因此您必须编写一个将格式字符串转换为正则表达式的方法。不是微不足道的,但可能。以下是您给出的2个测试用例的简单示例:

public static String getRegexpFromFormatString(String format)
{
    String toReturn = format;

    // escape some special regexp chars
    toReturn = toReturn.replaceAll("\\.", "\\\\.");
    toReturn = toReturn.replaceAll("\\!", "\\\\!");

    if (toReturn.indexOf("%") >= 0)
    {
        toReturn = toReturn.replaceAll("%s", "[\\\\w]+"); //accepts 0-9 A-Z a-z _

        while (toReturn.matches(".*%([0-9]+)[d]{1}.*"))
        {
            String digitStr = toReturn.replaceFirst(".*%([0-9]+)[d]{1}.*", "$1");
            int numDigits = Integer.parseInt(digitStr);
            toReturn = toReturn.replaceFirst("(.*)(%[0-9]+[d]{1})(.*)", "$1[0-9]{" + numDigits + "}$3");
        }
    }

    return "^" + toReturn + "$";
}

和一些测试代码:

public static void main(String[] args) throws Exception
{
    String formats[] = {"hello %s!", "song%03d.mp3", "song%03d.mp3"};
    for (int i=0; i<formats.length; i++)
    {
        System.out.println("Format in [" + i + "]: " + formats[i]);
        System.out.println("Regexp out[" + i + "]: " + getRegexp(formats[i]));
    }

    String[] words = {"hello world!", "song001.mp3", "potato"};
    for (int i=0; i<formats.length; i++)
    {
        System.out.println("Word [" + i + "]: " + words[i] +
            " : matches=" + words[i].matches(getRegexpFromFormatString(formats[i])));
    }
}

答案 3 :(得分:1)

没有一种简单的方法可以做到这一点。一种直截了当的方法是编写一些代码,将format strings(或其简单的子集)转换为正则表达式,然后使用标准正则表达式类匹配。

更好的方法可能是重新考虑/重构您的代码。你为什么要这个?

答案 4 :(得分:0)

您可以使用String.matches;虽然你需要使用正则表达式,而不是格式字符串。

使用\ d {3}正则表达式等效替换%03d之类的东西应该不会太难

示例:

  

“song001.mp3”。匹配(“song \\ d {3} \\。mp3”)// True

     

“potato”.matches(“song \\ d {3} \\。mp3”)//错误

如果你真的需要格式字符串,你需要创建一个用正则表达式替换格式的函数,并转义正则表达式保留字符;然后使用String.matches函数。

答案 5 :(得分:0)

字符串类有匹配方法,你可以在那里传递一个正则表达式。 String.matches(String)

对于正则表达式,你可以看到: http://download.oracle.com/javase/1,5.0/docs/api/java/util/regex/Pattern.html
示例:

"song001.mp3".matches("song\\d{3}\\.mp3");

答案 6 :(得分:-1)

您可以使用Pattern类来实现您想要的方法。请查看Pattern Java api页面中的示例。

相关问题