簡體   English   中英

使用Pattern和Matcher的Java正則表達式

[英]Java Regular Expressions using Pattern and Matcher

我的問題與Java中的正則表達式有關,特別是給定搜索模式的多個匹配。 我需要獲取的所有信息都在1行,它包含一個映射到IP地址的別名(例如SA)。 每個都用逗號分隔。 我需要提取每一個。

SA "239.255.252.1", SB "239.255.252.2", SC "239.255.252.3", SD "239.255.252.4"

我的Reg Ex看起來像這樣:

Pattern alias = Pattern.compile("(\\S+)\\s+\"(\\d+\\.\\d+\\.\\d+\\.\\d+)\"");  
Matcher match = alias.matcher(lineInFile)  
while(match.find()) {  
   // do something  
}

這可行,但我並不完全滿意,因為自從引入這一小段代碼后,我的程序已經放慢了一點(<1秒)但足以注意到差異。

所以我的問題是,我是否以正確的方式解決這個問題? 是否有更高效或可能輕量級的解決方案,而不需要一個while(匹配)循環? 和/或模式/匹配類?

如果該行可能不包含除別名定義之外的任何內容,則使用.match()而不是.find()可能會加快對非匹配的搜索。

我擔心你的代碼看起來非常有效。 這是我的版本:

Matcher match = Pattern
                .compile("(\\w+)\\s+\"(\\d+\\.\\d+\\.\\d+\\.\\d+)\"")
                .matcher(lineInFile);  
while(match.find()) {  
    //do something  
}

有兩個微優化:

  1. 無需將模式保存在額外的變量中,內聯它
  2. 對於別名,搜索單詞字符,而不是非空格字符

實際上,如果你做了很多這樣的處理並且模式永遠不會改變,你應該將編譯后的模式保持為常量:

private static final Pattern PATTERN = Pattern
            .compile("(\\w+)\\s+\"(\\d+\\.\\d+\\.\\d+\\.\\d+)\"");

Matcher match = PATTERN.matcher(lineInFile);  
while(match.find()) {  
    //do something  
}

更新:我花了一些時間在RegExr上提出了一個更具體的模式,它應該只檢測有效的IP地址作為獎勵。 我知道這很難看,但我的猜測是它非常高效,因為它消除了大部分的回溯:

([A-Z]+)\s*\"((?:1[0-9]{2}|2(?:(?:5[0-5]|[0-9]{2})|[0-9]{1,2})\.)
{3}(?:1[0-9]{2}|2(?:5[0-5]|[0-9]{2})|[0-9]{1,2}))

(為了便於閱讀,所有反斜杠都需要在java中進行轉義,但你可以在RegExr上測試它,因為它與OP的測試字符串一樣)

您可以將正則表達式改進為: "(\\\\S{2})\\\\s+\\"((\\\\d{1,3}\\\\.){3}\\\\d{1,3})\\""通過更明確地指定IP地址。

嘗試使用StringTokenizer的性能。 它不使用正則表達式。 (如果您擔心使用遺留類,那么請查看其源代碼並了解它是如何完成的。)

StringTokenizer st = new StringTokenizer(lineInFile, " ,\"");
while(st.hasMoreTokens()){
    String key = st.nextToken();
    String ip = st.nextToken();
    System.out.println(key + " ip: " +  ip);
}

我不知道這是否會產生很大的性能優勢,但你也可以先做

string.split(", ") // separate groups

然后

string.split(" ?\"") // separate alias from IP address

在比賽中。

預編譯和重用Pattern對象(IMO)可能是最有效的優化。 模式編譯可能是一個昂貴的步驟。

重用Matcher實例(例如使用reset(CharSequence) )可能有所幫助,但我懷疑它會有很大的不同。

正則表達式本身無法顯着優化。 一種可能的加速方式是用([0-9\\.]+)替換(\\d+\\.\\d+\\.\\d+\\.\\d+) ([0-9\\.]+) 這可能有所幫助,因為它減少了潛在回溯點的數量......但你需要做一些實驗才能確定。 明顯的缺點是它匹配的是無效IP地址的字符序列。

如果您注意到該段代碼的差異<1秒,那么您的輸入字符串必須包含大約一百萬(或至少大約100k)的條目。 我認為這是一個相當公平的性能,如果不編寫自己的專用解析器,我無法看到如何顯着優化它。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM