正则表达式匹配部分或驼峰案例字符串?

时间:2009-04-13 21:08:18

标签: java regex

我想要一个正则表达式来匹配给定的部分或驼峰的字符串。例如,如果搜索集包含字符串“MyPossibleResultString”,我希望能够将其与以下内容匹配:

  • MyPossibleResultString
  • MPRS
  • MPRString
  • MyPosResStr
  • 中号

我还想包括通配符匹配,例如:

  • MYP * RSTRING
  • * PosResString
  • 我*字符串

如果我不清楚我的意思,我能想到的唯一例子就是Eclipse的“Open Type”对话框,它几乎就是我正在寻找的确切行为。我对使用正则表达式并不太了解,所以如果我在寻找Java解决方案,我不确定它是否重要。

5 个答案:

答案 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等问题,其中在大写字母之后提供了小写字母(它们应该在大写字母后直接出现,而不是下一个)。