Java - 如何使用匹配器对可选的正则表达式模式进行编码

Java - How do I code optional regex patterns with a matcher

假设我正在遍历一个文本文件并遇到以下两个包含随机单词和整数值的字符串

“foo 11 25”
“foo 38 15 976 24”

我编写了一个匹配两个字符串的正则表达式模式,例如:

((?:[a-z][a-z]+)\s+\d+\s\d+)

但是,问题是我认为这个正则表达式不允许我获取第二个字符串中的所有 4 个整数值。

Q1.) 我怎样才能创建一个单一的模式,让这些第 3 和第 4 个整数可选?

Q2.) 如何编写匹配器代码,以便仅在模式找到第 3 个和第 4 个值之后进行匹配?

这是一个模板程序,可以帮助任何愿意提供帮助的人。谢谢

public void foo(String fooFile) {
        //Assume fooFile contains the two strings
        //"foo 11 25";
        //"foo 38 976 24";

        Pattern p = Pattern.compile("((?:[a-z][a-z]+)\s+\d+\s\d+)", Pattern.CASE_INSENSITIVE);

        BufferedReader br  = new BufferedReader(new FileReader(fooFile));
        String line;
        while ((line = br.readLine()) != null) {
            //Process the patterns
            Matcher m1 = p.matcher(line);
            if (m1.find()) {
                int int1, int2, int3, int4;
                //Need help to write the matcher code
            }
        }
    }

您当前使用的正则表达式模式末尾需要文本 \s\d\s\d。如果您希望它允许任意数量的数字,每个数字前面都有空格,您可以使用 (\s+\d+)+.

所以完整的正则表达式是 ((?:[a-z][a-z]+)(\s+\d+)+)

如果要检索每个 int 值,可以使用正则表达式:

[a-z]+\s(\d+)\s(\d+)\s?(\d+)?\s?(\d+)?

DEMO

并且每个 int 都将在 1 到 4 的组中。然后你可以使用类似的东西:

import java.util.ArrayList;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class Test {

    public static void main(String[] args){
        String[] strings = {"foo 11 25","foo 67 45 97",
        "foo 38 15 976 24"};

        for(String string : strings) {
            ArrayList<Integer> numbers = new ArrayList<Integer>();
            Matcher matcher = Pattern.compile("[a-z]+\s(\d+)\s(\d+)\s?(\d+)?\s?(\d+)?").matcher(string);
            matcher.find();
            for(int i = 0; i < 4; i++){
                if(matcher.group(i+1) != null) {
                     numbers.add(Integer.valueOf(matcher.group(i + 1)));
                }else{
                    System.out.println("group " + (i+1) + " is " + matcher.group(i+1));
                }
            }
            System.out.println("Match from string: "+ "\""+ string + "\"" + " : " + numbers.toString());
        }
    }
}

输出:

group 3 is null
group 4 is null
Match from string: "foo 11 25" : [11, 25]
group 4 is null
Match from string: "foo 67 45 97" : [67, 45, 97]
Match from string: "foo 38 15 976 24" : [38, 15, 976, 24]

另一种方法是将所有 int 归为一组:

[a-z]+\s((?:\d+\s?)+)

DEMO

并将 matcher.group(1) 与 space 拆分,您将得到 String[] 和值。 Java 中的实施:

public class Test {

    public static void main(String[] args){
        String[] strings = {"foo 11 25","foo 67 45 97",
        "foo 38 15 976 24"};

        for(String string : strings) {
            ArrayList<Integer> numbers = new ArrayList<Integer>();
            Matcher matcher = Pattern.compile("[a-z]+\s((?:\d+\s?)+)").matcher(string);
            matcher.find();
            String[] nums = matcher.group(1).split("\s");
            for(String num : nums){
                numbers.add(Integer.valueOf(num));
            }
            System.out.println("Match from string: "+ "\""+ string + "\"" + " : " + numbers.toString());
        }
    }
}

输出:

Match from string: "foo 11 25" : [11, 25]
Match from string: "foo 67 45 97" : [67, 45, 97]
Match from string: "foo 38 15 976 24" : [38, 15, 976, 24]