web-dev-qa-db-ja.com

文字列がフォーマット文字列と一致するかどうかを確認します

Javaでは、文字列が フォーマット文字列 (つまり: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

たぶん、フォーマット文字列を正規表現に変換する方法はありますか?

明確化

フォーマット文字列はパラメータです。事前にはわかりません。 song%03d.mp3は単なる例です。他のフォーマット文字列でもかまいません。

それが役立つ場合は、フォーマット文字列には1つのパラメーターしかないと想定できます。

14
hpique

私はそれを行う図書館を知りません。これは、フォーマットパターンを正規表現に変換する方法の例です。 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);
}
9
Cephalopod

これを行う簡単な方法はありません。簡単な方法は、 フォーマット文字列 (またはそれらのより単純なサブセット)を正規表現に変換し、標準の正規表現クラスを使用してそれらを照合するコードを作成することです。

より良い方法は、おそらくコードを再考/リファクタリングすることです。なぜこれが欲しいのですか?

1
dtech

Java正規表現を使用できます-参照してください http://www.vogella.de/articles/JavaRegularExpressions/article.html

ありがとう...

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])));
    }
}
1
JJ.

文字列クラスにはmatchesメソッドがあるので、そこに正規表現を渡すことができます。 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"); 
0
rascio

String.matches ;を使用できます。ただし、フォーマット文字列ではなく、正規表現を使用する必要があります。

%03dのようなものを\ d {3}正規表現に相当するものに置き換えるのはそれほど難しいことではありません

例:

"song001.mp3" .matches( "song \\ d {3} \\。mp3")// True

"potato" .matches( "song \\ d {3} \\。mp3")// False

本当にフォーマット文字列が必要な場合は、フォーマットを同等の正規表現に置き換え、正規表現の予約文字をエスケープする関数を作成する必要があります。次に、String.matches関数を使用します。

0
Yhn