多个相似的正则表达式,有更好的方法吗?

时间:2016-09-12 18:32:13

标签: java regex

我有一个文件,它由几个部分组成,由一个特定的字符串和字母分开,如下所示:

--673b0e57-A--
content here
--673b0e57-B--
content here
--673b0e57-C--
content here
--673b0e57-F--
content here

我创建了一个方法将其解析为一个像这样的对象:

for (String line:file) {
            if ((line.matches(".*-{1}[A]-{2}$") || currentPart == "A") && (!line.matches(".*-{1}[B|C|E|F|H|I|K|Z]-{2}$")) ) {
                currentPart = "A";
                //do stuff
            } else if ((line.matches(".*-{1}[B]-{2}$") || currentPart == "B") && (!line.matches(".*-{1}[C|E|F|H|I|K|Z]-{2}$")) ) {
                currentPart = "B";
                //do stuff
            } else if((line.matches(".*-{1}[C]-{2}$") || currentPart == "C") && (!line.matches(".*-{1}[E|F|H|I|K|Z]-{2}$")) ) {
                currentPart = "C";
                //do stuff
            } else if((line.matches(".*-{1}[E]-{2}$") || currentPart == "E") && (!line.matches(".*-{1}[F|H|I|K|Z]-{2}$")) ) {
                currentPart = "E";
                //do stuff
            } else if((line.matches(".*-{1}[F]-{2}$") || currentPart == "F") && (!line.matches(".*-{1}[H|I|K|Z]-{2}$")) ) {
                currentPart = "F";
                //do stuff
            } else if((line.matches(".*-{1}[H]-{2}$") || currentPart == "H") && (!line.matches(".*-{1}[I|K|Z]-{2}$")) ) {
                currentPart = "H";
                //do stuff
            } else if((line.matches(".*-{1}[I]-{2}$") || currentPart == "I") && (!line.matches(".*-{1}[K|Z]-{2}$")) ) {
                currentPart = "I";
                //do stuff
            } else if((line.matches(".*-{1}[K]-{2}$") || currentPart == "K") && (!line.matches(".*-{1}[Z]-{2}$")) ) {
                currentPart = "K";
                //do stuff
            } else if((line.matches(".*-{1}[Z]-{2}$") || currentPart == "Z")) {
                currentPart = "Z";
                //do stuff
            } else {
                System.out.println("No line marker to be found while parsing file!");
            }
        }

基本上发生的事情是: 1.检查是否A并记住是否如此 2.检查是否有其他字母,如果没有继续A,否则转到B. 等等

但我发现这个解决方案有点难看。有一个更好的方法吗?这可以是可读性或记忆力。我认识的人告诉我使用java.util.regex.Pattern。但据我所知,你仍然需要做同样的正则表达式,所以似乎根本没有奖金。我可能错过了什么吗?

亲切的问候

编辑: 好的,我已经看了@ brso05提出并由@Jeutnarg编写的解决方案,结果就是这样:

String[] strings = new String[]{"--673b0e57-A--", "blah", "--673b0e57-B--", "something", "hello"};
        Pattern p = Pattern.compile("--.*-([ABCEFHIKZ])--");
        String currentPart = null;
        StringBuilder builder = new StringBuilder();
        for(String s : strings)
        {
            Matcher m = p.matcher(s);
            if(m.find())
            {
                if(currentPart != null){
                    storeData(builder.toString(), currentPart);
                    System.out.println(builder.toString());
                }
                currentPart = m.group(1);
                System.out.println("Current part is "+m.group(1));
            }else{
                if(currentPart != null){
                    builder.append(s);
                }
            }
        }
        storeData(builder.toString(), currentPart);
        System.out.println(builder.toString());
    }

private void storeData(String data, String part){
        switch (part){
            case "A": //objectA
                break;
            case "B": //objectB
                break;
            ...
        }
    }

我认为它看起来好多了。没有那么多的模式需要加载等等。还有更多有趣的想法可以添加到这个吗?

2 个答案:

答案 0 :(得分:3)

正如brrso05指出的那样,捕获组可以做你想做的事情。使用捕获组(括号括起的部分)创建Pattern,然后为每个String创建一个Matcher对象。调用find(或匹配)以确定String是否有效,然后使用group(X)方法获得该匹配。

这是一个小代码,它会做你想要做的事情。您可能会注意到组(X)是1索引的,而不是0索引的。

String[] strings = new String[]{"hello", "blah", "--673b0e57-A--", "something", "--673b0e57-B--"};
    Pattern p = Pattern.compile("--.*-(\\w)--");
    for(String s : strings)
    {
        Matcher m = p.matcher(s);
        if(m.find())
        {
            System.out.println("Current part is "+m.group(1));
        }
    }

警告我 - 我创建的模式会匹配一些你可能不想匹配的东西,比如小写字母。在生产或重要的地方尝试之前,请进行自己的测试(我建议使用regex101.com快速测试正则表达式。)

答案 1 :(得分:1)

带有随机生成的文本的边界线的原因是为了确保可以生成与实际内容不匹配的边界线。这也意味着如果边界文本(随机生成的文本)是所有边界线上的相同,则一条线只是一条边界线。

由于您的文件必须以边界线开头,因此该第一行确定了此特定文件的边界文本。其他文件可能具有不同的边界文本。因此,您需要建立边界文本,并且只处理有效的边界线。

以下是执行此操作的示例代码。

String[] file = { "--673b0e57-A--",
                  "content here",
                  "--673b0e57-B--",
                  "content here",
                  "--673b0e57-C--",
                  "content here",
                  "--11111111-E--",
                  "content here",
                  "--673b0e57-F--",
                  "content here" };
Pattern boundaryPattern = Pattern.compile("--(.*?)-([ABCEFHIKZ])--");
String boundaryText = null, currentPart = null;
for (String line : file) {
    Matcher m = boundaryPattern.matcher(line);
    if (m.matches()) {
        if (boundaryText == null) {
            boundaryText = m.group(1);
            currentPart = m.group(2);
            continue;
        } else if (m.group(1).equals(boundaryText)) {
            if (m.group(2).compareTo(currentPart) <= 0)
                throw new IllegalStateException("Line marker out of sequence: " + m.group(2) +
                                                                  " must be > " + currentPart);
            currentPart = m.group(2);
            continue;
        }
    } else if (boundaryText == null) {
        throw new IllegalStateException("No line marker to be found while parsing file!");
    }
    System.out.println("Part " + currentPart + ": " + line);
}

输出

Part A: content here
Part B: content here
Part C: content here
Part C: --11111111-E--
Part C: content here
Part F: content here

如您所见,无效边界线被视为内容,应该是。