【问题标题】:Java Regex to extract an id string, based on recurring sub-string of each idJava Regex 根据每个 id 的重复子字符串提取 id 字符串
【发布时间】:2017-07-14 15:41:44
【问题描述】:

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

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

我从其他帖子中尝试了许多不同的建议。但我没有成功,有以下模式:

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

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

【问题讨论】:

  • "一个日志文件并提取文件中包含的某些数据" - 什么样的数据,什么样的日志文件?发布一个例子。
  • @user3734782150: 2017-06-14 18:02:21 INFO monitorinfo : Info: Lock VCS on node "ieatrcxb4498-1" 这是来自日志文件的数据样本。
  • 所以你想提取包含 id 的整行?
  • @user3734782 不只是它自己的 id。文件的每一行都有一个 id,并希望从每一行中获取 id。如上所示,我已经用时间完成了。

标签: java regex pattern-matching matcher


【解决方案1】:

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} 表示“最少出现 4 次,最多出现 6 次”(这只是一个示例,我不知道您是否属于这种情况)。如果您确切知道 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)

这只会返回4498

【讨论】:

    【解决方案2】:
    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);
    

    【讨论】:

      【解决方案3】:

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

      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 号,只需删除/注释第二个和第三个 .map() 方法调用,但它会生成一个字符串列表而不是整数。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2023-01-07
        • 1970-01-01
        • 2019-10-13
        • 2020-06-10
        • 1970-01-01
        • 2020-11-26
        • 1970-01-01
        相关资源
        最近更新 更多