我想要一个正则表达式来匹配给定的部分或驼峰的字符串。例如,如果搜索集包含字符串“MyPossibleResultString”,我希望能够将其与以下内容匹配:
我还想包括通配符匹配,例如:
如果我不清楚我的意思,我能想到的唯一例子就是Eclipse的“Open Type”对话框,它几乎就是我正在寻找的确切行为。我对使用正则表达式并不太了解,所以如果我在寻找Java解决方案,我不确定它是否重要。
答案 0 :(得分:4)
好的,如果你已经支持第一个例子中描述的匹配,我真的不明白为什么你需要通配符功能。这就是我放在一起的东西。给定查询字符串查询,使用正则表达式创建正则表达式:
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。
中返回第一个匹配您的驼峰案例查询 编辑:我已经添加了一行来处理通配符,因为在我疲倦的昏迷中我并不理解他们的需要答案 1 :(得分:2)
正如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());
}
查询:MyP * RString
创建一个模式:My。* P. * R. * String。*
答案 2 :(得分:1)
使用单个正则表达式无法执行此操作。您必须根据输入构建正则表达式并使用它来搜索。很容易看出你不能使用单个正则表达式 - 用户可以搜索任何(cammel cased)字符串,所以你的正则表达式需要匹配任何(cammel cased)字符串,但它不再是搜索。
答案 3 :(得分:0)
您可以尝试以下方式:
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}
和不情愿的量词*?
的说明,请参阅Pattern API。
示例测试用例:
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)));
}
}
答案 4 :(得分:0)
Il-Bhima的衣服很棒,但我发现这段代码对我来说效果更好(原谅我的C#,但它是一样的):
pattern = Regex.Escape(pattern);
pattern = pattern.Replace(@"\*", ".*?");
pattern = Regex.Replace(pattern, "([A-Z][^A-Z]*)", "$1[^A-Z]*?") + ".*";
注意最后的“。*”允许不完整的“startof”短语(也不允许指定所有大写字母) 此外,“[^ AZ] *”匹配器后面的星号修复了工具包的答案中的q4等问题,其中在大写字母之后提供了小写字母(它们应该在大写字母后直接出现,而不是下一个)。