Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/360.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/regex/18.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何提高这个正则表达式的效率_Java_Regex_Parsing_Java.util.scanner - Fatal编程技术网

Java 如何提高这个正则表达式的效率

Java 如何提高这个正则表达式的效率,java,regex,parsing,java.util.scanner,Java,Regex,Parsing,Java.util.scanner,我认为我使用的正则表达式模式可以整理一下,看起来更整洁一些,但我对正则表达式的了解有限。我想扫描并匹配输入文件中新行上的一系列字母和数字 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

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

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;
  }

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

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

你目前的模式不是很精确,与你描述的相反。有很多
+?
,但是您的描述非常清楚地说
两个字母
总是a=
——因此您可以在您的模式中使用它。您的模式还包含十进制数,而显示的输入中没有十进制数,因此您可以删除
(?:\\d*\\)?
。此外,所有数字匹配模式都是可选的,但根据您的描述,X不应该

如果你完全按照字面理解你的模式,一个可能的模式就是

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


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

除非正则表达式包含回溯,并且您可以删除它,否则实际上没有优化正则表达式这样的事情。您可以优化它的外观,但所有执行相同操作的正则表达式都编译为相同的DFA或等效DFA,并具有相同的性能。

在您的模式中,您使用了大量的
+?
,其中您的描述中显示了
两个字母
始终是a=
-您可以像描述一样具体,所以使用
[a-z]{2}
a=
。此外,您的正则表达式还包含十进制数,而显示的输入中没有十进制数,因此您可以删除
(?:\\d*\\)?
。此外,所有的数字匹配模式都是可选的,为什么?因此,如果您的输入总是按照这里显示的方式进行,那么您可能会像java中使用的双反斜杠一样具体。这很好。谢谢@SebastianProskeI没有能力将此答案标记为正确答案,因为它不是答案,只是要求澄清的评论。由于我所有的假设似乎都是正确的,我会在几分钟后写一个答案,只是先去吃晚饭:)错。它们要么编译为dfa,要么编译为nfa,并且它们的性能不同。例如,如果在文本编辑器中搜索regexp,则文本编辑器可能会将regexp编译为NFA,并将传递闭包应用于非确定性搜索,或者可以将传递闭包应用于NFA,并获得非优化DFA,并应用确定性搜索。如果在这两种情况下都没有优化DFA/NFA,则速度会变慢,因为边/ε边的数量会变大。可以肯定的是,如果编译器编译为NFA并动态应用t.c,则速度会变慢(如果未优化)。如果编译成DFA,很难说它们是否具有相同的性能。
([a-z]{2})-(\\d+)\\n[Aa]=(\\d+)\\n([a-z])-(\\d+)