我想在字符串中搜索标识符。标识符可以有变化
REF964758362562
REF964-758362-562
964758362562
964-758362-562
标识符可以位于字符串中的任何位置,也可以位于其自身上。例如:
Lorem ipsum REF964-758362-562
Lorem ipsum ABCD964-758362-562 lorem ipsum
Lorem ipsum REF964-758362-562 lorem ipsum
REF964-758362-562 Lorem ipsum 1234-123456-22
Lorem ipsum 964-758362-562 lorem ipsum
REF964758362562
REF964-758362-562
964758362562
964-758362-562
当在标识符中使用连字符/短划线字符时,连字符将始终显示在示例中所示的第3和第9位之后。
这是我提出的,但我怀疑正则表达式太长,可能会缩短。这也适用于 标识符不在字符串的开头。任何提示/想法?
^[A-Z]*REF[A-Z]*([12]\d{3})(\d{6})(\d{2})$|^([12]\d{3})(\d{6})(\d{2})[A-Z]*REF[A-Z]*|^([12]\d{3})(\d{6})(\d{2})$
我已将它们分组,因为一旦我提取了标识符,我想添加连字符,如果标识符没有连字符。例如,如果
提取的标识符为964758362562
,我想将其另存为964-758362-562
。
以下是我运行的一些测试,因为你可以看到很多测试都没有匹配
testRegex = "^[A-Z]*REF[A-Z]*([12]\\d{3})(\\d{6})(\\d{2})$|^([12]\\d{3})(\\d{6})(\\d{2})[A-Z]*REF[A-Z]*|^([12]\\d{3})(\\d{6})(\\d{2})$";
PATTERN = Pattern.compile(testRegex, Pattern.CASE_INSENSITIVE);
m = PATTERN.matcher("Lorem ipsum REF964-758362-562");
if(m.matches()) {
System.out.println("Match = " + m.group());
}else{
System.out.println("No match");
}
m = PATTERN.matcher("REF964-758362-562 Lorem ipsum 1234-123456-22");
if(m.matches()) {
System.out.println("Match = " + m.group());
}else{
System.out.println("No match");
}
m = PATTERN.matcher("Lorem ipsum 964-758362-562 lorem ipsum");
if(m.matches()) {
System.out.println("Match = " + m.group());
}else{
System.out.println("No match");
}
m = PATTERN.matcher("Lorem ipsum ABCD964-758362-562 lorem ipsum");
if(m.matches()) {
System.out.println("Match = " + m.group());
}else{
System.out.println("No match");
}
m = PATTERN.matcher("REF964758362562");
if(m.matches()) {
System.out.println("Match = " + m.group());
}else{
System.out.println("No match");
}
m = PATTERN.matcher("REF964-758362-562");
if(m.matches()) {
System.out.println("Match = " + m.group());
}else{
System.out.println("No match");
}
m = PATTERN.matcher("964758362562");
if(m.matches()) {
System.out.println("Match = " + m.group());
}else{
System.out.println("No match");
}
m = PATTERN.matcher("964-758362-562");
if(m.matches()) {
System.out.println("Match = " + m.group());
}else{
System.out.println("No match");
}
输出
No match
Match = Not known
No match
No match
No match
No match
No match
No match
No match
No match
答案 0 :(得分:4)
使用此正则表达式:
(REF)?964-?758362-?562
?使前一组可选,零或一次出现。
“REF”是可选的,短划线是可选的。
要强制两个破折号都在那里,请使用此正则表达式
(REF)?964-758362-562|(REF)?964758362562
答案 1 :(得分:2)
看起来标识符遵循这种一般模式:
在这种情况下,这种模式将起作用
(?>REF)?(\\d{3}+)(-?)(\\d{6}+)\\2(\\d{3}+)
打破模式:
(?>REF)?
一个匹配“REF”的原子组,可选(\\d{3}+)
占有3位数,占有(第1组)(-?)
捕获可选连字符(第2组)(\\d{6}+)
占有6位数,占有(第3组)\\2
反向引用第二组中捕获的内容(\\d{3}+)
占有3位数,占有(第4组)漂亮的技巧是捕获可选的连字符然后反向引用它,这样如果第一个连字符存在则第二个必须是;相反,如果第一个连字符不存在,则第二个连字符不能存在。
Java中的测试用例:
public static void main(String[] args) throws Exception {
final String[] test = {"Lorem ipsum REF964-758362-562",
"Lorem ipsum ABCD964-758362-562 lorem ipsum",
"REF964-758362-562 Lorem ipsum 1234-123456-22",
"Lorem ipsum 964-758362-562 lorem ipsum",
"REF964758362562",
"REF964-758362-562",
"964-758362562",
"964758362-562",
"964758362562",
"964-758362-562"};
final Pattern patt = Pattern.compile("(?>REF)?(\\d{3}+)(-?)(\\d{6}+)\\2(\\d{3}+)");
final MessageFormat format = new MessageFormat("{0}-{1}-{2}");
for (final String in : test) {
final Matcher mat = patt.matcher(in);
while (mat.find()) {
final String id = format.format(new Object[]{mat.group(1), mat.group(3), mat.group(4)});
System.out.println(id);
}
}
}
输出:
964-758362-562
964-758362-562
964-758362-562
964-758362-562
964-758362-562
964-758362-562
964-758362-562
964-758362-562
您的主要问题是使用Matcher.matches()
,需要整个输入才能匹配模式。你真正想要的是找到输入中的 模式。为此目的,有while(Matcher.find())
成语 - 它依次在输入中找到模式的每次出现。
答案 2 :(得分:2)
其他答案的想法非常好,但如果您不想接受只有123-123456123
这样的短划线的标识符,您应该使用类似
(REF)?(\\d{3}-\\d{6}-\\d{3}|\\d{12})
//which means
// REF
// and after that numbers in form
// XXX-XXXXXX-XXX OR XXXXXXXXXXXX
// where X represents any digit
你可以用\b
这个正则表达式包围,这是一个单词边界,以确保它是单独的单词,而不是其他单词的一部分。
答案 3 :(得分:1)
您可能希望使用m.find()
代替m.matches()
:
testRegex = "(?:REF)?(\\d{3})(-?)(\\d{6})\\2(\\d{3})";
PATTERN = Pattern.compile(testRegex, Pattern.CASE_INSENSITIVE);
m = PATTERN.matcher(
"Lorem ipsum REFREF964-758362-562\n" +
"Lorem ipsum ABCD964-758362-562 lorem ipsum\n" +
"Lorem ipsum REF964-758362-562 lorem ipsum\n" +
"REF964-758362-562 Lorem ipsum 1234-123456-22\n" +
"Lorem ipsum 964-758362-562 lorem ipsum\n" +
"REF964758362562\n" +
"REF964-758362-562\n" +
"964758362562\n" +
"964-758362-562");
while(m.find()) {
System.out.println(m.group(1)+"-"+m.group(3)+"-"+m.group(4));
}