Regex這個文法以簡單高效著稱,但是有一點i就是比較複雜。
近期有個功能需要去除字串中重複的部分,由於使用正常的傳統的那種舒服拆分成數組在一個一個匹配的方式感覺有點效率過低浪費效能,於是便想到了Regex來匹配重複的字串,並利用String自導的replaceAll方法來將相應的字串給刪除掉。
目標字串:
"10110,10254,10554,11025,10254,11002,11532,10110,";
這是一個數字數組,但是這裡面有某些ID是重複的,我必須將之去除掉。由於我對正則文法實在不熟悉,都是臨時對著說明文檔在使用的階段。沒有比較好的思路,所以去網上查了些思路。
發現一個類似的解決方案,去除重複的字母具體代碼如下:
String str = "aaaaaaahdbkjsdnfkjsndjkfsdfsdf"; str = str.replaceAll("(?s)(.)(?=.*\\1)", ""); System.out.println(str); 大致看了下說明意思。
(?s) 開啟單行模式 DOTALL 讓. 號匹配任一字元
(.) 任一字元 並捕獲在第一組
(?=.*\1) 這是斷言, 表示後面內容將是 任意個字元加上第一組所捕獲的內容
第一條:開啟正則的某些模式,感覺跟我沒多少關係,我這是要去除重複的字串,他這是去字母。
從第二條看過去來看,關鍵應該是分組,大致是思路我有點印象了,還是說匹配某個字串,然後添加了個斷言,第三條就是那個斷言,也就是說將當前字串做一個分組,放到斷言裡去了之後,匹配重複的部分。然後我對著將我的需求修改了一下。
String reg = "(\\d{5},)(?=(\\d{5},)*\\1)";
具體代碼如下
String str = "abcdeabcdeabcdeaaaaaadddddceeeeabcccccccacadaeec"; String str1 = "10110,10254,10554,11025,10254,11002,11532,10110,";String reg = "(\\d{5},)(?=(\\d{5},)*\\1)";str = str.replaceAll("(?s)(.)(?=.*\\1)", ""); str1 = str1.replaceAll(reg, "");//str = str.replaceAll(reg, ""); System.out.println(str1); 一開始是斷言裡面沒有加 * 導致匹配失敗,我猜測如果不加的話將會只匹配一組了。
但是後來我發現這個裡面有個限制,就是該字串數組就會被我限制在5個裡面,如果其中有某一條字串超過了5位元,則會導致匹配失敗,這可能是個不足,因為我現在在講6個作為一組,然後一組一組的匹配的,所以才會有這個問題,如果是其他的話,應該就不會有這個問題了。
OK,暫時算是解決問題了。這個斷言還是有點不好理解,感覺有點預言性質,但是又不是進入實際的匹配對象裡面去,主要是用處大概是對當前是匹配對象做進一步的限制和條件,以增強匹配的正確性。這個可能需要做進一步的測試才能得知。先做到這了,斷言還有很多用途(?<=exp)、(?=exp)、(?!exp)、(?<!exp)等多種方式,每一種還會有各種細微的差別,這個先下去研究,等有個靠譜的結論了在說好了。