Java 用于提取 id 字符串的正则表达式,基于每个 id 的重复子字符串

Java Regex to extract an id string, based on recurring sub-string of each id

我正在读取日志文件并提取文件中包含的某些数据。我能够提取日志文件每一行的时间。

现在我想提取 id "ieatrcxb4498-1"。所有 id 都以我尝试查询的子字符串 ieatrcxb 和基于它的完整字符串 return 开头。

我尝试了很多来自其他帖子的不同建议。但是我一直没有成功,模式如下:

(?i)\b("ieatrcxb"(?:.+?)?)\b
(?i)\b\w*"ieatrcxb"\w*\b"
^.*ieatrcxb.*$ 

我还尝试根据以 i 开始并在 1 结束的字符串提取完整的 ID。就像他们一样。

日志文件行

150: 2017-06-14 18:02:21 INFO  monitorinfo           :     Info: Lock VCS on node "ieatrcxb4498-1"

代码

Scanner s = new Scanner(new FileReader(new File("lock-unlock.txt")));
    //Record currentRecord = null;
    ArrayList<Record> list = new ArrayList<>();

    while (s.hasNextLine()) {
        String line = s.nextLine();

        Record newRec = new Record();
        // newRec.time =
        newRec.time = regexChecker("([0-1]?\d|2[0-3]):([0-5]?\d):([0-5]?\d)", line);

        newRec.ID = regexChecker("^.*ieatrcxb.*$", line);

        list.add(newRec);

    }


public static String regexChecker(String regEx, String str2Check) {

    Pattern checkRegex = Pattern.compile(regEx);
    Matcher regexMatcher = checkRegex.matcher(str2Check);
    String regMat = "";
    while(regexMatcher.find()){
        if(regexMatcher.group().length() !=0)
            regMat = regexMatcher.group();
        }
        //System.out.println("Inside the "+ regexMatcher.group().trim());
    }

     return regMat;
}

我需要一个简单的模式来为我做这件事。

public static void main(String[] args) {
    String line = "150: 2017-06-14 18:02:21 INFO  monitorinfo           :     Info: Lock VCS on node \"ieatrcxb4498-1\"";
    String regex ="ieatrcxb.*1";
    Pattern p = Pattern.compile(regex);
    Matcher m = p.matcher(line);
    while(m.find()){
        System.out.println(m.group());
    }
}

或者如果 ID 都被引用:

 String id = line.substring(line.indexOf("\""), line.lastIndexOf("\"")+1);
 System.out.println(id);

你正试图通过非常困难的方式来做到这一点。如果 lock-unlock.txt 文件的每一行都与您发布的片段相同,您可以执行以下操作:

File logFile = new File("lock-unlock.txt");

List<String> lines = Files.readAllLines(logFile.toPath());

List<Integer> ids = lines.stream()
                .filter(line -> line.contains("ieatrcxb"))
                .map(line -> line.split( "\"")[1]) //"ieatrcxb4498-1"
                .map(line -> line.replaceAll("\D+","")) //"44981"
                .map(Integer::parseInt) // 44981
                .collect( Collectors.toList() );

如果您不只是查找 ID 号,只需 remove/comment 第二次和第三次 .map() 方法调用,但结果将是字符串列表而不是整数。

ID 是否始终采用“ieatrcxb 后跟 4 位数字,后跟 -,后跟 1 位数字”的格式?

如果是这样,你可以这样做:

regexChecker("ieatrcxb\d{4}-\d", line);

请注意 {4} 量词,它恰好匹配 4 位数字 (\d)。如果最后一位总是 1,您也可以使用 "ieatrcxb\d{4}-1".

如果位数不同,可以使用"ieatrcxb\d+-\d+",其中+表示“1个或多个”。

您还可以将 {} 量词与最小和最大出现次数一起使用。示例:"ieatrcxb\d{4,6}-\d" - {4,6} 表示 "minimum of 4 and maximum of 6 occurrences"(这只是一个例子,我不知道你的情况是否如此)。如果您确切知道 ID 可以包含多少位数字,这将非常有用。

以上所有工作都适用于您的案例,返回 ieatrcxb4498-1。使用哪一个将取决于您的输入如何变化。


如果您只想要没有 ieatrcxb 部分的数字 (4498-1),您可以使用 lookbehind regex:

regexChecker("(?<=ieatrcxb)\d{4,6}-\d", line);

这使得 ieatrcxb 不属于匹配项,因此只返回 4498-1

如果您也不想要 -1 而只想要 4498,您可以将其与前瞻相结合:

regexChecker("(?<=ieatrcxb)\d{4,6}(?=-\d)", line)

这个returns只是4498