Java 要从部分或驼峰大小写字符串匹配的正则表达式?
我想要一个正则表达式来匹配给定的部分或大小写字符串。例如,如果搜索集包含字符串“MyPossibleResultString”,我希望能够将其与以下类似项匹配:Java 要从部分或驼峰大小写字符串匹配的正则表达式?,java,regex,Java,Regex,我想要一个正则表达式来匹配给定的部分或大小写字符串。例如,如果搜索集包含字符串“MyPossibleResultString”,我希望能够将其与以下类似项匹配: MyPossibleResultString MPRS MPRString 桃金娘 M 我还希望包括通配符匹配,例如: MyP*RString *PosResString 我的*字符串 如果不清楚我的意思,我能想到的唯一例子就是Eclipse的“开放式”对话框,这正是我要寻找的行为。我不太熟悉正则表达式的使用,所以我不确定在Ja
- MyPossibleResultString
- MPRS
- MPRString
- 桃金娘
- M
- MyP*RString
- *PosResString
- 我的*字符串
如果不清楚我的意思,我能想到的唯一例子就是Eclipse的“开放式”对话框,这正是我要寻找的行为。我不太熟悉正则表达式的使用,所以我不确定在Java中寻找解决方案是否重要。单用一个正则表达式是不可能做到这一点的。您必须基于输入构建一个正则表达式,并使用它进行搜索。很容易看出,您不能使用单个正则表达式-用户可以搜索任何(cammel cased)字符串,因此您的正则表达式需要匹配任何(cammel cased)字符串,但它不再是搜索了。正如danbruc所说,您必须为每个新查询生成一个新正则表达式。这段代码应该满足您的要求
public Pattern queryToPattern(String query) {
StringBuilder sb = new StringBuilder();
char[] chars = query.toCharArray();
boolean incamel = false;
for (int i=0; i < chars.length; i++) {
if (chars[i] == '*') {
if (!incamel)
sb.append(".*");
} else if (Character.isUpperCase(chars[i])) {
if (incamel) {
sb.append(".*");
}
sb.append(chars[i]);
incamel = true;
} else {
sb.append(chars[i]);
}
}
sb.append(".*");
return Pattern.compile(sb.toString());
}
公共模式查询模式(字符串查询){
StringBuilder sb=新的StringBuilder();
char[]chars=query.toCharArray();
布尔incamel=false;
for(int i=0;i
对:MyP*RString的查询
创建一个模式:My.*p.*R.*String.*Ok,因此如果您已经可以支持第一个示例中描述的匹配,我真的不明白为什么需要通配符功能。这就是我所说的。给定查询字符串查询,可以使用正则表达式创建正则表达式:
String re = "\\b(" + query.replaceAll("([A-Z][^A-Z]*)", "$1[^A-Z]*") + ".*?)\\b";
例如,查询MyPosResStr
将成为正则表达式:
\\b(My[^A-Z]*Pos[^A-Z]*Res[^A-Z]*Str[^A-Z]*.*?)\\b
然后使用Matcher.find
方法使用此正则表达式进行匹配,得到如下结果:
public static String matchCamelCase(String query, String str) {
query = query.replaceAll("\\*", ".*?");
String re = "\\b(" + query.replaceAll("([A-Z][^A-Z]*)", "$1[^A-Z]*") + ".*?)\\b";
System.out.println(re);
Pattern regex = Pattern.compile(re);
Matcher m = regex.matcher(str);
if (m.find()) {
return m.group();
} else return null;
}
这将返回字符串str中第一个匹配的驼峰大小写查询
编辑:我添加了一行代码来处理通配符,因为在我疲惫不堪的昏迷中,我没有意识到需要通配符您可以尝试以下方法:
class RegexTransformer {
public String fromQuery(String query) {
StringBuilder sb = new StringBuilder();
sb.append("^");
sb.append(query.replaceAll("(\\p{Upper}(?!\\p{Lower}))",
"$1\\\\p{Alpha}*?"));
sb.append("$");
return sb.toString();
}
}
请参阅,以获取有关消极先行断言(?!pat)
、POSIX字符类\p{class}
和不情愿量词*?
的说明
示例测试用例:
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import org.junit.Test;
public class RegexTransformerTest {
private RegexTransformer rt = new RegexTransformer();
@Test
public void testQueries() {
String in = "MyPossibleResultString";
String q1 = "MyPossibleResultString";
String q2 = "MPRS";
String q3 = "MPRString";
String q4 = "MyPosResStr"; // this wont work
String q5 = "M";
test(in, q1, "^MyPossibleResultString$");
test(in, q2, "^M\\p{Alpha}*?P\\p{Alpha}*?R\\p{Alpha}*?S\\p{Alpha}*?$");
test(in, q3, "^M\\p{Alpha}*?P\\p{Alpha}*?R\\p{Alpha}*?String$");
test(in, q5, "^M\\p{Alpha}*?$");
}
private void test(String in, String query, String expected) {
assertEquals("transform", expected, rt.fromQuery(query));
assertTrue("match", in.matches(rt.fromQuery(query)));
}
}
Il Bhima的answear很棒,但我发现这段代码对我来说更好(请原谅我的C#,但它是一样的): 注意末尾的“*”允许使用不完整的“startof”短语(也允许不指定所有大写字母)
此外,“[^A-Z]*”匹配器后面的星号修复了工具箱答案中第四个问题,即小写字母在大写字母之后(它们应该直接出现在大写字母之后,而不是在下一个大写字母之前)。如果Eclipse的行为与您所寻找的行为非常相似,那么,你能不能看看伊柯丽斯的源代码?我可以,当我继续寻找答案时,我会考虑这个选项:-你的意思是,例如,输入字符串“MyPosirS”将被解析来生成“MyPoSRS”的正则表达式,这可以匹配吗?是的,您必须根据用户输入生成一个正则表达式,并使用它进行搜索。您现在无法构建一个,因为您不知道输入,因此不知道正则表达式必须匹配什么。好的,这是有意义的。现在看起来很明显+1第一个示例不包括我希望“*PRS”匹配的情况,而“PRS”不应该匹配的情况。我想说的是,在编辑之前,它对一些模式不起作用,现在唯一不匹配的示例是没有显式悬空通配符的'M'/'MP'/'MPR'等。我相信这只是一个小因素,我确实喜欢它更简洁(我相信我很快就能读到它:-D)+1谢谢你抓住它!你说得对,那是我错过的另一个案子。接下来。如果目标字符串以小写“my”开头,regexp会是什么样子?i、 e.mPosResStr应该匹配。这是一种享受,目前为+1,但我会让时间成熟起来,看看另一个答案是否更好(在我无知的情况下,我目前无法真正判断这一点)。谢谢
pattern = Regex.Escape(pattern);
pattern = pattern.Replace(@"\*", ".*?");
pattern = Regex.Replace(pattern, "([A-Z][^A-Z]*)", "$1[^A-Z]*?") + ".*";