給大家分享一段手機號或或者貨幣格式化的程式碼

發表於2019-05-11

最近在做一個專案的時候遇到這樣一個需求:客戶讓我把手機號碼顯示為 138-8888-8888的格式。

心想這還不簡單,不加思索的敲下了這段程式碼:

function format_mobile($mobile){
    return implode('-', sscanf($mobile, '%3s%4s%4s'));
}

執行之後得到結果正是我想要的。可是,我總覺得這就完了?難道沒有更簡單的方法了?

思考片刻又寫了這樣一個函式:

function format_mobile2($mobile){
    return preg_replace('/^(\d{3})(\d{4})(\d{4})$/', '$1-$2-$3', $mobile);
}

執行,挺好,也能得到正確的結果。不過這個好像也沒有比上面更簡單,少呼叫一個函式而已,但是程式碼還變多了。。。

接著,需求又來了,所有的檔案大小用位元組為單位,但是從又往左每三位用逗號分割。

看到這個需求的第一反應是,剛格式化手機號碼的第二種方案不正好麼,4位改三位,分隔符換掉就OK。

開始編寫程式碼,當寫到正規表示式的時候發現,完了,手機號位數確定的,檔案位元組大小位數不定的。繼續思考,調整了正規表示式如下:

function format_filesize($filesize){
    return preg_replace('/(\d)(?=(\d{3})+$)/', '$1,', $filesize);
}

執行,結果正確。

這裡,我解釋一下這段正規表示式:

(\d) //第一個括號主要是用來匹配一個數字
     //我們要往這個數字的後面新增一個逗號
     
(?=) //第二個括號是一個正向肯定查詢
     //也就是說,前面匹配的那個數字後面的字串必須符合這個括號裡面的規則
     
(\d{3})+$ //這是第二個括號裡面的規則
          //這裡又有一個括號,這個括號僅代表 \d{3} 為一個整體
          //\d{3} 匹配3個數字
          //後面的 + 號代表前面括號的內容可以出現 N 次,N >= 1
          //(\d{3})+ 即為匹配3的倍數個數字
          //最後的 $ 匹配字串的結尾,即3的倍數個數字之後不能再有任何字元

//根據上面的解釋,我們可以看出:
//這段正規表示式主要是用來找一個數字,這個數字的特徵是
//後面的字元必須是3的倍數個數字,只到結尾
//例如:1234567890這10個數字
//後面為3的倍數個數字的數字分別為1,4,7
//那我們只需要找到它們,分別在它們的後面新增逗號就OK了

然後,又想到,在做電商專案的時候,經常遇到金額的格式化,也是沒三位新增一個逗號。少有不同的是,金額不是從字串結尾開始算的,而是從小數點開始往左邊數的。

仔細想想,繼續調整正規表示式:

function format_amount($amount){
    return preg_replace('/(\d)(?=(\d{3})+\.)/', '$1,', $amount);
}

上面格式化檔案位元組大小的時候我們是匹配的3的倍數個數字直到字元結尾,這裡因為是到小數點,所以我們只需要把字元結尾 $ 改為 \. 即可。

仔細看看上面三個正規表示式替換的函式,我們又可以發現它們的共同點:

  1. 需要找到一個數字,並在這個數字的後面新增一個符號
  2. 這個數字都有相同的規律,後面的數字的長度都是某一個長度的倍數,直到一個不為數字的字元結束
  3. 在找到的這些數字的後面新增的符號都是一樣的

有了上面這些條件,我們就可以把上面的三個函式改寫成一個函式:

/**
 * 從右往左根據指定的位數往一段數字中插入指定的符號
 * @param  string  $number 要分隔的數字字串
 * @param  integer $b      分隔的位數
 * @param  string  $d      分隔符
 * @return string          分隔後的字串
 */
function format_number($number, $b = 3, $d = ','){
    return preg_replace('/(\d)(?=(\d{' . $b . '})+(?!\d))/', '$1' . $d, $number);
}

echo format_number('1234567890'); //1,234,567,890
echo format_number('12345678.90'); //12,345,678.90
echo format_number('13888888888', 4, '-'); //138-8888-8888

這樣,我們需要格式化的資料就可以通過這一個函式搞定了。

以上只是我個人的一些思路,如果哪位童鞋還有更好的方法,歡迎交流!!!

評論(4)

相關文章