我尝试了以下regx(java字符串格式):
^(.*(iOS\\s+[\\d\\.]+|Android\\s+[\\d\\.]+)?.*)$
要匹配的字符串是:
Some Money 2.6.2; iOS 5.1.1
它假设返回三组:
group[0] :Some Money 2.6.2; iOS 5.1.1
group[1] :Some Money 2.6.2; iOS 5.1.1
group[2] :iOS 5.1.1
但它实际上会返回这些:
group[0] :Some Money 2.6.2; iOS 5.1.1
group[1] :Some Money 2.6.2; iOS 5.1.1
group[2] :null
当我改变正则表达式如下
^(.*(iOS\\s+[\\d\\.]+|Android\\s+[\\d\\.]+).*)$
但它不能像
那样匹配字符串whatever iS 5.1.1 whatever
我想要实现的是正则表达式返回三组,无论字符串是什么。第一组和第二组始终是整个字符串。第三组是匹配'(iOS | Android)[\ d。] *'的子字符串。如果string确实包含该部分,如果它不包含,则为null或为空。
答案 0 :(得分:2)
也许您可以使用;
分隔符作为iOS 5.1.1
部分开始的指示?
然后模式可能看起来像.+;\\s+(.+)
。
.+;
消耗一切直至分号\\s+
使用分号和版本字符串(.+)
消耗所有内容直到最后如果您真的只想匹配 iOS 或 Android ,那么您可能希望在(.+)
部分中添加非捕获组。
然后regexp看起来像这样:".+;\\s+((?:iOS|Android).+)"
。
这里有一个可执行的示例,解决方案可能是什么样子。它显示了我在上面解释的两种模式变体的行为。
public static void main(String[] args) {
String input1 = "Some Money 2.6.2; iS 5.1.1 ";
String input2 = "Some Money 2.6.2; iOS 5.1.1 ";
String input3 = "Some Money 2.6.2; Android 5.1.1 ";
String pattern1 = ".+;\\s+(.+)";
String pattern2 = ".+;\\s+((?:iOS|Android).+)";
System.out.println(pattern1);
matchPattern(input1, pattern1);
matchPattern(input2, pattern1);
matchPattern(input3, pattern1);
System.out.println();
System.out.println(pattern2);
matchPattern(input1, pattern2);
matchPattern(input2, pattern2);
matchPattern(input3, pattern2);
}
private static void matchPattern(String input, String pattern) {
Pattern p = Pattern.compile(pattern);
Matcher m = p.matcher(input);
if(m.matches()) {
System.out.println(m.group(0));
System.out.println(m.group(1));
if(m.groupCount() > 1) {
System.out.println(m.group(2));
}
}
}
更新:由于作者的某些修改,问题的目标更加清晰,我觉得有必要更新我的答案。如果它总是得到三个组,则以下可能比制定所有可能的符号变体更好:
public static void main(String[] args) {
String input1 = "Some Money 2.6.2; iS 5.1.1";
String input2 = "Some Money 2.6.2; iOS 5.1.1";
String input3 = "Some Money 2.6.2; Android 5.1.1";
String input4 = "Some Money 2.6.2 iOS 5.1.1";
String input5 = "Some Money 2.6.2 iOS";
String input6 = "Some Money 2.6.2";
String pattern1 = "(.*?((?:iOS|Android)(?:\\s+[0-9\\.]+)?.*)?)";
System.out.println(pattern1);
matchPattern(input1, pattern1);
matchPattern(input2, pattern1);
matchPattern(input3, pattern1);
matchPattern(input4, pattern1);
matchPattern(input5, pattern1);
matchPattern(input6, pattern1);
}
private static void matchPattern(String input, String pattern) {
Pattern p = Pattern.compile(pattern);
Matcher m = p.matcher(input);
if(m.matches()) {
System.out.println(m.group(0));
System.out.println(m.group(1));
System.out.println(m.group(2));
System.out.println();
}
}
此处的模式为(.*?(?:((?:iOS|Android)(?:\\s+[0-9\\.]+)?).*)?)
。
.*?
会占用版本字符串之前的所有内容。如果没有可用的版本字符串,则它匹配整个输入。 此处需要Reluctant quantifier。它需要仍然匹配的最短匹配,因此避免消耗整个输入。 (?:((?:iOS|Android)(?:\\s+[0-9\\.]+)?).*)?
使用整个版本字符串以及随后的所有内容。((?:iOS|Android)(?:\\s+[0-9\\.]+)?)
是组(2)输出。它只是匹配操作系统字符串 iOS 或 Android ,带有由数字和点组成的可选版本后缀。答案 1 :(得分:0)
请参考this topic关于" RegEx引擎如何运作"。
- 基于反向跟踪的。这些通常将模式编译成字节码,类似于机器指令。然后引擎执行代码,从指令跳转到指令。当指令失败时,它会回溯以找到另一种匹配输入的方式。
醇>
您的正则表达式有很多方法可以匹配输入。可悲的是,它以另一种方式返回(不是你预期的匹配)。
删除"?"来自第二组的量词,它变为" required"。 您返回的商品将匹配所有必需的组。
答案 2 :(得分:0)
我终于用正则表达式解决了这个问题,如下所示。
(.*((?:iOS|Android)\\s+[0-9\\.]+).*|.*)