【问题标题】:Java regex extract specific values in long logJava 正则表达式在长日志中提取特定值
【发布时间】:2020-10-27 08:36:07
【问题描述】:

我有一个很长的文本,我正在提取一些特定的值,然后是一些特定的单词。这是我的长文本示例:

.........
FPS(FramesPerSecond)[ValMin: 29.0000, ValMax: 35.000]
.........
TotalFrames[ValMin: 100000, ValMax:200000]
.........
MemoryUsage(In MB)[ValMin:190000MB, ValMax:360000MB]
.........

这是我的代码:

File file = filePath.toFile();
        JSONObject jsonObject = new JSONObject();
String FPSMin="";
String FPSMax="";
String TotalFramesMin="";
String TotalFramesMax="";
String MemUsageMin="";
String MemUsageMax="";

String log = "my//log//file";

        final Matcher matcher = Pattern.compile("FPS/\(FramesPerSecond/\)/\[ValMin:");
        if(matcher.find()){
            FPSMin= matcher.end().trim();
        }

但我不能让它工作。我哪里错了?基本上,我需要为每个字符串选择来自该长文本的相应值(最大值和最小值)并将它们存储到变量中。喜欢

FPSMin = 29.0000
FPSMax = 35.0000
FramesMin = 100000
Etc 

谢谢

编辑: 我尝试了以下代码(在测试用例中)以查看解决方案是否可行,但我遇到了问题,因为除了对象之外我无法打印任何东西。代码如下:

 @Test
    public void whenReadLargeFileJava7_thenCorrect()
            throws IOException, URISyntaxException {
        Scanner txtScan = new Scanner("path//to//file//test.txt");


        String[] FPSMin= new String[0];
        String FPSMax= "";
  
//Read File Line By Line
        while (txtScan.hasNextLine())   {
            // Print the content on the console
            String str = txtScan.nextLine();
            Pattern FPSMin= Pattern.compile("^FPS\\(FramesPerSecond\\)\\[ValMin:");
            Matcher matcher = FPSMin.matcher(str);

            if(matcher.find()){
                String MinMaxFPS= str.substring(matcher.end(), str.length()-1);
                String[] splitted = MinMaxFPS.split(",");
                FPSMin= splitted[0].split(": ");
                FPSMax = splitted[1];

            }

            System.out.println(FPSMin);
            System.out.println(FPSMax);

        }

【问题讨论】:

  • 不确定您想要实现什么,但您的代码甚至无法编译。我经常想知道为什么人们在使用正则表达式而不是首先尝试使用简单的方法(子字符串)。
  • 我需要从文本日志中选择值并使用正则表达式将它们存储到变量中。例如,FPS 最小值、FPS 最大值等
  • @Smutje 如何使用子字符串做到这一点?这是一个日志文件,但很长
  • 我建议通过删除所有不必要的代码行(例如文件部分)来简化您的示例,以缩小正则表达式不起作用的原因。此外,如果其他人可以在他们的机器上编译您的代码而无需额外开销,这也有助于其他人为您提供帮助。

标签: java regex extract matcher


【解决方案1】:

也许你的模式应该是这样的 ^FPS\\(FramesPerSecond\\)\\[ValMin: 。我已经尝试过了,它对我有用。

    String line = "FPS(FramesPerSecond)[ValMin: 29.0000, ValMax: 35.000]";
    
    Pattern pattern = Pattern.compile("^FPS\\(FramesPerSecond\\)\\[ValMin:");
    
    Matcher matcher = pattern.matcher(line);
    
    if (matcher.find()) {
        
        System.out.println(line.substring(matcher.end(), line.length()-1));
        
    }
}

通过这种方式,您可以获得要提取数据的行的偏移​​量,并使用 substring 函数可以获得从偏移量开始直到第 1 行大小的所有字符(因为您也不想获得] 字符)

【讨论】:

  • 你能告诉我你的代码吗?它对我不起作用,它说我需要将匹配器修改为模式
  • @thranduil90 这是因为Pattern#compile 返回的是Pattern 而不是Matcher,
  • 太完美了,谢谢!但是如何将 Min 和 Max 存储在不同的变量中?
  • @Smutje 谢谢,我解决了 Pattern 和 Matcher 的问题。现在我只需要理清如何选择 Min 和 Max 并将它们分配给不同的变量
  • 一种方法是使用 split() 函数。使用我提到的上述代码获得结果 ValMin: 29.000, ValMax: 35.000 后,您可以执行 String[] splitted = result.split(",") 其中 result 是存储上述代码结果的字符串,在 splitted[0] 上,您将拥有 ValMin: 29.000 和在 splitted[1] 上,您将拥有 ValMax:35.000。然后以同样的方式你可以做String[] minVal = splitted[1].split(": ") 并且在 minVal[1] 上你会得到 29.000。同样,对 ValMax 执行相同操作
【解决方案2】:

以下正则表达式将匹配并捕获名称、最小值和最大值:

Pattern.compile("(.*)\\[.+:\\s*(\\d+(?:\\.\\d+)?)[A-Z]*,.+:\\s*(\\d+(?:\\.\\d+)?)[A-Z]*\\]");

用法(提取捕获的组):

String input = (".........\n" +
        "FPS(FramesPerSecond)[ValMin: 29.0000, ValMax: 35.000]\n" +
        ".........\n" +
        "TotalFrames[ValMin: 100000, ValMax:200000]\n" +
        ".........\n" +
        "MemoryUsage(In MB)[ValMin:190000MB, ValMax:360000MB]\n" +
        ".........");

for (String s : input.split("\n")) {
    Matcher matcher = pattern.matcher(s);
    if (matcher.matches()) {
        System.out.println(matcher.group(1) + ", " + matcher.group(2) + ", " + matcher.group(3));
    }
}

输出:

FPS(FramesPerSecond), 29.0000, 35.000
总帧数, 100000, 200000
MemoryUsage(MB), 190000, 360000

【讨论】:

  • 谢谢!但这些点只是一个例子,里面有很多无用的文字。如何修改模式以仅包含 Frames、TotalFrames 和 MemoryUsage?
  • 不再匹配第一个方括号 (.*) 之前的任何内容,而是只匹配 (FPS\(FramesPerSecond\)|TotalFrames|MemoryUsage\(In MB\))。或者您使用原始模式,并按第一组过滤(如果名称在这三个名称的集合内)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-11-06
  • 1970-01-01
  • 1970-01-01
  • 2022-08-08
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多