Java 验证字符串是否与格式字符串匹配

Java 验证字符串是否与格式字符串匹配,java,regex,string,string-formatting,Java,Regex,String,String Formatting,在Java中,如何确定字符串是否与(即:歌曲%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 match

在Java中,如何确定字符串是否与(即:
歌曲%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
也许有办法把格式字符串转换成正则表达式

澄清
格式字符串是一个参数。我事先不知道<代码>歌曲%03d.mp3只是一个例子。它可以是任何其他格式字符串

// 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());
}

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

您可以使用Pattern类实现该方法来执行您想要的操作。查看页面中的示例。

您可以使用Java正则表达式-请参阅

谢谢…

您可以使用;尽管您需要使用正则表达式,而不是格式字符串

// 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());
}
用\d{3}regex等价物替换像%03d这样的东西应该不会太难

例如:

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

“potato”.matches(“song\\d{3}\\\.mp3”)//False


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

由于您事先不知道格式,因此必须编写一个将格式字符串转换为regexp的方法。不是琐碎的,而是可能的。下面是您给出的两个测试用例的简单示例:

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])));
    }
}
publicstaticvoidmain(字符串[]args)引发异常
{
字符串格式[]={“你好%s!”,“歌曲%03d.mp3”,“歌曲%03d.mp3”};

对于(inti=0;istring类有matches方法,您可以在那里传递一个regex。

对于正则表达式,您可以看到以下内容:
示例:

"song001.mp3".matches("song\\d{3}\\.mp3"); “song001.mp3”。匹配(“song\\d{3}\\\.mp3”);
要做到这一点,没有简单的方法。一种直接的方法是编写一些代码,将其转换(或更简单的子集)为正则表达式,然后与使用标准正则表达式类的代码进行匹配


更好的方法可能是重新思考/重构代码。为什么要这样做?

我不知道有哪个库可以这样做。下面是一个如何将格式模式转换为正则表达式的示例。请注意,
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());
}

格式字符串是一个参数。我事先不知道它。歌曲%03d.mp3只是一个例子。@hgpc ok我已经适当地修改了我的答案。这比我通常对SO答案所做的要多,但我很感兴趣。:)您必须完善/完成这一点以供生产使用,但这是一个在必要时如何实现这一点的想法。格式字符串是一个参数。我事先不知道它。宋%03d.mp3只是一个例子。因此,我对用其正则表达式等价物替换%03d等格式代码的评论:)。您链接的页面完全定义了如果是可能的代码和前缀,您需要编写一个函数来搜索并替换这些代码。a%d将被替换为\d+;%03d可能成为\d{3}\d?(以确保最小值为3,但可能是“无限的”数字。格式字符串是一个参数。我事先不知道。宋%03d.mp3只是一个例子。但是你必须写一个正则表达式…这是我不明白的…正则表达式是如何创建的?你需要一些自动创建正则表达式的东西?或者你需要一些检查字符串是否包含正则表达式的东西?以及如何转换通用的f将字符串转换为模式?我很想使用正则表达式,但我得到的是一个格式字符串。这是我想要避免的。我没有编写完整的代码。完全没有本地方法可以做到这一点。因此,你要么重新考虑你的输入/代码,编写你自己的转换器,要么找到一个这样做的转换器。例如,你到底为什么要这样做我们选择格式字符串是因为它们在所有平台上都几乎相同,不像regex。好吧,如果你把它作为java应用程序的参数,为什么不直接使用java regexps呢?因为java应用程序是接收此输入的众多客户端之一。+1这或多或少是我现在正在做的。比ks用于发布代码。如果你想成为英雄,你可以将你的代码发布为开源。我对发布开源代码并不陌生,但这太具体了,无法发布。