Java 在正则表达式中使用通配符会导致扫描效率低下

Java 在正则表达式中使用通配符会导致扫描效率低下,java,regex,Java,Regex,我有一个文本文件(大于7GB),其中填充了重复的行,如下所示,其中每行10.00和2.00可能不同: startline money earned 10.00 "300 plus nums n words here" money start 2.00 more words 我想获得值10.00和2.00 我的正则表达式如下所示: money earned ([0-9\.]+).*money start ([0-9\.]+) 但这是荒谬的效率低下。我花了将近30分钟扫描了1%的文本文件!似乎是

我有一个文本文件(大于7GB),其中填充了重复的行,如下所示,其中每行10.00和2.00可能不同:

startline money earned 10.00 "300 plus nums n words here" money start 2.00 more words
我想获得值10.00和2.00

我的正则表达式如下所示:

money earned ([0-9\.]+).*money start ([0-9\.]+)
但这是荒谬的效率低下。我花了将近30分钟扫描了1%的文本文件!似乎是
*
导致了这种效率低下。因此,我选择使用两个单独的正则表达式行来获取这些值,如下所示,这同样有效,而且效率更高

money earned ([0-9\.]+) //this is line 1 capturing 10.00
money start ([0-9\.]+)  //this is line 2 capturing 2.00
但是这会导致赚来的钱(10.00)首先被捕获,因为它是每行的第一部分,钱开始(2.00)最后是第二部分


我想扭转这一局面,并能够为每一行首先捕获金钱起点(2.00),然后捕获金钱收益(10.00)。有没有办法我可以把正则表达式倒过来,从后面开始,移到前面。或者,无论如何,我可以克服用一行正则表达式扫描时效率低下的问题

您是否能够在java程序接管之前预处理您的文件

我使用您的示例作为模板创建了一个7.1GB文件。然后,我使用grep对其进行预处理,以创建一个中介文件,该文件可以更容易地由java处理

time grep -Eo 'money (earned|start) \d+\.\d+' large_file.txt > results.txt

real    3m12.306s
user    3m7.701s
sys     0m3.222s
创建
results.txt
文件只需大约三分钟,仅168M,格式如下:

money earned 10.00
money start 2.00
money earned 10.00
money start 2.00 
money earned 10.00
money start 2.00

您是否能够在java程序接管之前预处理您的文件

我使用您的示例作为模板创建了一个7.1GB文件。然后,我使用grep对其进行预处理,以创建一个中介文件,该文件可以更容易地由java处理

time grep -Eo 'money (earned|start) \d+\.\d+' large_file.txt > results.txt

real    3m12.306s
user    3m7.701s
sys     0m3.222s
创建
results.txt
文件只需大约三分钟,仅168M,格式如下:

money earned 10.00
money start 2.00
money earned 10.00
money start 2.00 
money earned 10.00
money start 2.00
这是你的问题。这是一场贪婪的比赛。这意味着它在回溯之前开始尽可能多的匹配,并尝试更短的匹配以允许剩余的正则表达式匹配。因此,如果您有大量数据,或者有很长的行(甚至是很长的字符串,取决于
是否匹配换行符),这可能需要一些时间。这还取决于数据的外观。如果在最后一次
金钱启动之后出现大量文本,则需要更长的时间。如果行中有多个
money start
,则跳过除最后一个之外的所有内容

您可以尝试使用
*?
来代替,这是一种惰性匹配,即,它从尽可能少的代码开始并扩展它。在许多情况下,这要快得多

这是你的问题。这是一场贪婪的比赛。这意味着它在回溯之前开始尽可能多的匹配,并尝试更短的匹配以允许剩余的正则表达式匹配。因此,如果您有大量数据,或者有很长的行(甚至是很长的字符串,取决于
是否匹配换行符),这可能需要一些时间。这还取决于数据的外观。如果在最后一次
金钱启动之后出现大量文本,则需要更长的时间。如果行中有多个
money start
,则跳过除最后一个之外的所有内容


您可以尝试使用
*?
来代替,这是一种惰性匹配,即,它从尽可能少的代码开始并扩展它。在许多情况下,这要快得多。

您尝试过这个正则表达式吗<代码>金钱(?:挣得的开始)([0-9\.]+)
?您是将整个文件作为一个7GB字符串读取,还是一次读取一行?字符串解析是否允许
匹配新行?您需要提供更多的细节。您是一次编译
模式并重用它,还是每次阅读一行内容时都重新创建它?@AJNeufeld一次一行。当我这样做的时候,我试图跳过所有的数百行,从同一行开始。这些线路有一些敏感数据。对不起,我们不是要求你发布敏感数据。拿出你的代码,把它剥离到能再现你的问题的最低限度,然后发布。我们可以获取代码,修改它,从我们自己的7GB日志文件中搜索一些类似的数据,并验证其效率低下,这样我们就可以确定瓶颈实际是什么,而不仅仅是猜测。您尝试过这个正则表达式吗<代码>金钱(?:挣得的开始)([0-9\.]+)
?您是将整个文件作为一个7GB字符串读取,还是一次读取一行?字符串解析是否允许
匹配新行?您需要提供更多的细节。您是一次编译
模式并重用它,还是每次阅读一行内容时都重新创建它?@AJNeufeld一次一行。当我这样做的时候,我试图跳过所有的数百行,从同一行开始。这些线路有一些敏感数据。对不起,我们不是要求你发布敏感数据。拿出你的代码,把它剥离到能再现你的问题的最低限度,然后发布。我们可以获取代码,修改它,从我们自己的7GB日志文件中搜索一些类似的数据,并验证其效率低下,这样我们就可以确定瓶颈实际是什么,而不仅仅是猜测。您是否尝试先用Java直接处理文件,以复制问题?您是否尝试先用Java直接处理文件,复制这个问题?