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つのパラメーターしかないと想定できます。
私はそれを行う図書館を知りません。これは、フォーマットパターンを正規表現に変換する方法の例です。 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);
}
これを行う簡単な方法はありません。簡単な方法は、 フォーマット文字列 (またはそれらのより単純なサブセット)を正規表現に変換し、標準の正規表現クラスを使用してそれらを照合するコードを作成することです。
より良い方法は、おそらくコードを再考/リファクタリングすることです。なぜこれが欲しいのですか?
Java正規表現を使用できます-参照してください http://www.vogella.de/articles/JavaRegularExpressions/article.html
ありがとう...
事前にフォーマットがわからないため、フォーマット文字列を正規表現に変換するメソッドを作成する必要があります。些細なことではありませんが、可能です。これはあなたが与えた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])));
}
}
文字列クラスには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");
String.matches ;を使用できます。ただし、フォーマット文字列ではなく、正規表現を使用する必要があります。
%03dのようなものを\ d {3}正規表現に相当するものに置き換えるのはそれほど難しいことではありません
例:
"song001.mp3" .matches( "song \\ d {3} \\。mp3")// True
"potato" .matches( "song \\ d {3} \\。mp3")// False
本当にフォーマット文字列が必要な場合は、フォーマットを同等の正規表現に置き換え、正規表現の予約文字をエスケープする関数を作成する必要があります。次に、String.matches関数を使用します。