【问题标题】:How would you improve the efficiency of this regex您将如何提高此正则表达式的效率
【发布时间】:2017-07-16 14:21:31
【问题描述】:

我认为我使用的正则表达式模式可以整理一下,看起来更整洁一些,但我对正则表达式的了解有限。我想扫描并匹配输入文件中新行上的一系列字母和数字。

import java.io.File;
import java.util.Scanner;

import java.util.regex.*;

public class App {
    public static void main(String[] args) throws Exception {

    if (args.length == 1) {

        String fileName = args[0];
        String fileContent = new Scanner(new File(fileName))
                .useDelimiter("\\Z").next();

        ArrayList<Integer> parsedContent = new ArrayList<>();
        parsedContent = parseContentFromFileContent(fileContent);

        int firstInt = parsedContent.get(0);
        int secondInt = parsedContent.get(1);
        int thirdInt = parsedContent.get(2);
        int fourthInt = parsedContent.get(3);
        int fifthInt = parsedContent.get(4);

        System.out.println("First: " + firstInt);
        System.out.println("Second: " + secondInt);
        System.out.println("Third: " + thirdInt);
        System.out.println("Fourth: " + fourthInt);
        System.out.println("Fifth: " + fifthInt);

        return;
    }
  }

  public static ArrayList<Integer> parseContentFromFileContent(String fileContent) {

    ArrayList<Integer> parsedInts = new ArrayList<>();

    String pattern = "(.+?).((?:\\d*\\.)?\\d+)?\\n..((?:\\d*\\.)?\\d+)?\\n(.+?).((?:\\d*\\.)?\\d+)";
    Pattern p = Pattern.compile(pattern, Pattern.DOTALL);
    Matcher m = p.matcher(fileContent);

    if (m.matches()) {
        // Group 1: Has to match two letters
        switch (m.group(1)) {
            case "ab":
                parsedInts.add(1);
                break;
            case "cd":
                parsedInts.add(2);
                break;
            case "ef":
                parsedInts.add(3);
                break;
        }

        // Group 2: Has to match a number
        parsedInts.add(Integer.parseInt(m.group(2)));

        // Group 3: Has to match a letter
        parsedInts.add(Integer.parseInt(m.group(3)));

        // Group 4: Has to match a single letter
        switch (m.group(4)) {
            case "a":
                parsedInts.add(1);
                break;
            case "b":
                parsedInts.add(2);
                break;
            case "c":
                parsedInts.add(3);
                break;
        }
        // Group 5: Has to match a number
        parsedInts.add(Integer.parseInt(m.group(5)));
    }
    return parsedInts;
  }

}

输入文件:

ab-123 // Group 1 - Two letters a-z and Group 2 - Number
A=1    // Group 3 - Always A= [number]
a-1    // Group 4 - Letter a-z and Group 5 - Number

cd-1234
A=2
b-2

ef-12345
a=4
c-3

gh-123456
a=4
d-4

有没有更好(更干净)的正则表达式模式可以用来从上面的文件中捕获数据。

pattern = (.+?).((?:\\d*\\.)?\\d+)?\\n..((?:\\d*\\.)?\\d+)?\\n(.+?).((?:\\d*\\.)?\\d+)

【问题讨论】:

  • 在你的模式中,你使用了很多.+?,你的描述是two lettersalways A=——你可以和你的描述一样具体,所以使用[a-z]{2}A=。此外,您的正则表达式考虑十进制数,而显示的输入中没有,因此您可以删除(?:\\d*\\.)?。此外,您所有的号码匹配模式都是可选的,为什么?
  • 所以如果你的输入总是像这里显示的那样,你可能像([a-z]{2})-(\d+)\n[Aa]=(\d+)\n([a-z])-(\d+)一样具体,在java中使用双反斜杠。
  • 太好了。谢谢@SebastianProske
  • 我无法将此答案标记为正确
  • 因为这不是答案,只是要求澄清的评论。看来我所有的假设都是正确的,我会在稍后写一个答案,先去吃饭:)

标签: java regex parsing java.util.scanner


【解决方案1】:

与您给出的描述相反,您目前的模式不是很精确。有很多.+?,但你的描述很清楚地写着two lettersalways A= - 所以你可以在你的模式中使用它。您的模式还考虑了十进制数字,而显示的输入中没有,因此您可以删除(?:\\d*\\.)?。此外,您所有的号码匹配模式都是可选的,但根据您的描述,不应该。

如果有人按照字面意思理解你的模式,那么可能的模式就是

([a-z]{2})-(\\d+)\\n[Aa]=(\\d+)\\n([a-z])-(\\d+)

https://regex101.com/r/WNxUQa/1

请注意,如果可能存在恶意输入,您可能需要稍微调整一下您的模式(例如,使用 ^$)。

【讨论】:

    【解决方案2】:

    实际上没有优化正则表达式这样的事情,除非它包含回溯并且您可以将其删除。您可以优化它外观的方式,但是所有做同样事情的正则表达式都会编译成相同的 DFA 或等效的 DFA,并具有相同的性能。

    【讨论】:

    • 错误。它们编译为 dfa 或 nfa 并且它们没有相同的性能。例如,如果您在文本编辑器中搜索正则表达式,文本编辑器可能会将正则表达式编译为 NFA 并动态应用传递闭包以进行非确定性搜索,或者它可以将传递闭包应用于 NFA 并获得未优化的 DFA 并应用确定性搜索。如果你不在这两种情况下优化 DFA/NFA,它会随着边数/epsilong 边数的增加而变慢。
    • 可以肯定的是,如果编译器编译为 NFA 并动态应用 t.c.如果未优化,它会更慢。如果它编译为 DFA,很难说它们是否具有相同的性能。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-07-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-06-06
    • 2022-12-05
    相关资源
    最近更新 更多