簡體   English   中英

使用Java中的regex格式化字符串

[英]Format a string using regex in Java

有沒有什么辦法可以使用正則表達式將字符串格式化為特定模式,或者是stringbuilder + substring更快的方法?

例如,輸入電話號碼 - > 1234567890

輸出為 - >(123)456-7890

我看到這篇文章是可能的: http//www.4guysfromrolla.com/webtech/031302-1.shtml但是給出的解釋是在ASP中。 我怎么用Java做的???

放棄

由於幾個答案已經解決了字符串構建器等的更高效率,我想向您展示如何使用正則表達式完成它並解決使用此方法的好處。

一個REGEX解決方案

使用這個匹配的正則表達式(類似於Alan Moore的表達式 ):

(.{3})(.{3})(.{4})

允許您將10個字符精確匹配到3個組中,然后使用引用這些組的替換表達式,並添加其他字符:

($1) $2-$3

從而按照您的要求生產替換品。 當然,它也會匹配標點符號和字母,這是使用\\d (編碼為Java字符串為\\\\d )而不是. 通配符。

為何選擇REGEX?

這種類型的正則表達式方法的潛在優勢是對字符串操作的“邏輯”壓縮。 由於所有“邏輯”都可以壓縮成一串字符而不是預編譯的代碼,因此正則表達式匹配和替換字符串可以存儲在數據庫中,以便系統的有經驗的用戶更容易地操作,更新或定制。 這使得情況在幾個層面上變得更加復雜,但為用戶提供了更大的靈活性。

與其他方法(字符串處理),改變格式的算法,使其產生(555)123-4567555.123.4567 ,而不是您指定的(555) 123-4567將基本上不僅僅是通過用戶界面成為可能。 使用正則表達式方法,修改就像將($1) $2-$3 (在數據庫或類似商店中)更改為$1.$2.$3($1)$2-$3一樣簡單。

如果你想修改你的系統以接受“更臟”的輸入,這可能包括各種格式化嘗試,例如555-123.4567並將它們重新格式化為一致的東西,那么就可以制作一個能夠實現的字符串操作算法。這個並重新編譯應用程序以實現您的工作方式。 然而,使用正則表達式解決方案,系統大修不是必需的 - 只需更改解析和替換表達式(對於初學者來說可能有點復雜):

^\D*1?\D*([2-9])\D*(\d)\D*(\d)\D*(\d)\D*(\d)\D*(\d)\D*(\d)\D*(\d)\D*(\d)\D*(\d).*$
($1$2$3) $4$5$6-$7$8$9$10

這將允許程序能力的重大“升級”,如下面的重新格式化所示:

"Input"                       "Output"
----------------------------- --------------------------------
"1323-456-7890 540"           "(323) 456-7890"
"8648217634"                  "(864) 821-7634"
"453453453322"                "(453) 453-4533"
"@404-327-4532"               "(404) 327-4532"
"172830923423456"             "(728) 309-2342"
"jh345gjk26k65g3245"          "(345) 266-5324"
"jh3g24235h2g3j5h3"           "(324) 235-2353"
"12345678925x14"              "(234) 567-8925"
"+1 (322)485-9321"            "(322) 485-9321"
"804.555.1234"                "(804) 555-1234"
"08648217634"                 <no match or reformatting>

正如您所看到的,它對輸入“格式化”非常“寬容”,並且知道在數字的開頭應該忽略1 ,並且0應該導致錯誤,因為它是無效的 - 所有都存儲在單個字符串中。

問題歸結為性能與定制潛力。 字符串操作比正則表達式更快,但未來的增強自定義需要重新編譯而不是簡單地更改字符串。 也就是說,有些東西不能很好地表達(或者甚至以與上述變化一樣的可讀方式)和一些正則表達式無法實現的東西。

TL; DR:

Regex允許將解析算法存儲到一個相對較短的字符串中,該字符串可以很容易地存儲,以便可以在不重新編譯的情況下進行修改。 更簡單,更集中的字符串操作函數更有效,並且有時可以比正則表達式更有效。 關鍵是要了解應用程序的工具和要求,並使用最適合的情況。

如果使用substring無法完成,或者更難以這樣做,則可以使用RE

在你的情況下,最好只使用StringBuilderinsert()

假設電話號碼長度驗證到位(= 10個字符)

        String phoneNumber = "1234567890";
        StringBuilder sb = new StringBuilder(phoneNumber)
                                .insert(0,"(")
                                .insert(4,")")
                                .insert(8,"-");
        String output = sb.toString();
        System.out.println(output);          

產量

(123)456-7890

相同的技術適用於Java; 你只需要調整Java語法和API:

s = s.replaceFirst("(\\d{3})(\\d{3})(\\d{4})", "($1) $2-$3");

不過,我不明白為什么你會問更快的方法。 你嘗試過這樣的事情並遇到性能問題嗎? 你幾乎可以肯定使用StringBuilder更有效地做到這一點,但實際上,它幾乎肯定不值得努力。

或者你是否正在談論用一個正則表達式來學習如何使用StringBuilder手工編寫它的時間? 不過,現在這是一個有爭議的問題。 :d

我會使用java String.format()方法和String.substring()

帶有groups的正則表達式匹配器實際上只是一些String容器,加上大量的RE匹配代碼。 (你實際上可以查看源代碼並自己查看。)這不比自己使用substring()便宜,尤其是在你的情況下使用固定的偏移量。

帶子字符串的StringBuilder會更快,但並不總是最簡單/最好的方法。 在這種情況下,我只會使用substring。

String num = "1234567890";
String formatted = "(" + num.substring(0,3) + ") "
     + num.substring(3,6) + "-" + num.substring(6); 

暫無
暫無

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

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