我需要在运行时生成一个与一系列数值匹配的正则表达式。
例如:在运行时,我可能会发现我需要一个正则表达式,匹配“范围”a-261-b.something
到a-543-b.something
中的所有文件。
我需要生成一个匹配所有这些文件的正则表达式。有什么想法吗?
我需要用Java编写,所以如果有人知道任何特定于Java的方法,那么它也是可以接受的。
谢谢!
答案 0 :(得分:13)
正则表达式是否适合此任务是值得商榷的。大多数人可能会争辩说不是。
但据我所知,你没有选择,因为你正在使用的API将正则表达式作为参数,所以这里...
public class NumericRangeRegexGenerator {
private static String baseRange(String num, boolean up, boolean leading1) {
char c = num.charAt(0);
char low = up ? c : leading1 ? '1' : '0';
char high = up ? '9' : c;
if (num.length() == 1)
return charClass(low, high);
String re = c + "(" + baseRange(num.substring(1), up, false) + ")";
if (up) low++; else high--;
if (low <= high)
re += "|" + charClass(low, high) + nDigits(num.length() - 1);
return re;
}
private static String charClass(char b, char e) {
return String.format(b==e ? "%c" : e-b>1 ? "[%c-%c]" : "[%c%c]", b, e);
}
private static String nDigits(int n) {
return nDigits(n, n);
}
private static String nDigits(int n, int m) {
return "[0-9]" + String.format(n==m ? n==1 ? "":"{%d}":"{%d,%d}", n, m);
}
private static String eqLengths(String from, String to) {
char fc = from.charAt(0), tc = to.charAt(0);
if (from.length() == 1 && to.length() == 1)
return charClass(fc, tc);
if (fc == tc)
return fc + "("+rangeRegex(from.substring(1), to.substring(1))+")";
String re = fc + "(" + baseRange(from.substring(1), true, false) + ")|"
+ tc + "(" + baseRange(to.substring(1), false, false) + ")";
if (++fc <= --tc)
re += "|" + charClass(fc, tc) + nDigits(from.length() - 1);
return re;
}
private static String nonEqLengths(String from, String to) {
String re = baseRange(from,true,false) + "|" + baseRange(to,false,true);
if (to.length() - from.length() > 1)
re += "|[1-9]" + nDigits(from.length(), to.length() - 2);
return re;
}
public static String rangeRegex(int n, int m) {
return rangeRegex("" + n, "" + m);
}
public static String rangeRegex(String n, String m) {
return n.length() == m.length() ? eqLengths(n, m) : nonEqLengths(n, m);
}
}
// Generate expression for range 123 - 321
String regexp = NumericRangeRegexGenerator.rangeRegex(123, 321);
代码的简要说明如下。
0000
- abcd
和abcd
- 9999
首先我们注意到0000
- abcd
等匹配范围非常简单。
例如000
- 527
的表达式可以表示为
[0-4]
后跟两个任意数字,或5
后跟00
- 27
(递归解析!)形状1000
- abcd
和abcd
- 9999
的范围同样简单。
如果“from” - 数字比“to”数字短,则相当直接。
假设例如from
- 数字有3位数,to
- 数字有7位数。然后表达式可以如下组成:
from
- 999
(如上所述),4
,5
或6
位数:[1-9][0-9]{3-5}
或1000000
- to
(如上所述)这是最棘手的情况(但仍然不是 虽然棘手!)
再一次,最好通过一个例子来描述解决方案。考虑范围273
- 548
。表达式可以由以下部分组成:
2
后跟73
- 99
(后面描述的部分),[34]
后跟任意两位数字,或5
后跟00
- 48
(后面描述的部分)答案 1 :(得分:1)
让我看看我是否正确理解这一点。您有一个名为a-NUMBER-b.txt的文件。您需要检查号码是否正确。这是如何完成的:
要检查数字,请假设格式正确:
String name = getName();
int myInt = Integer.parseInt(name.split(a + "-")[1].split("-" + b + ".txt")[0]);
检查格式:
name.startsWith(a + "-") && name.endWith("-" + b + ".txt")
如果我回答正确,请告诉我 莱恩
答案 2 :(得分:0)
这样的事情可能有用,但不确定拆分的成本。
File[] files = new File("foo").listFiles();
for( int i = 0; i < files.length; i++ )
{
String fn = files[i].getName();
String sl[] = fn.split( "-" );
int num = Integer.parseInt( sl[1] );
if( num >= min && num <= max )
//do stuff
}