PHP 依照「位置」來快速分割固定格式文字

PHP 要快速分割固定格式的文字,可以使用 split、explode 等等,但是若是一串連續的字串,該怎麼做呢?

固定字串例如:20171110235959 (2017年11月10日23點59分59秒)

一般想到最快的就是 preg_match 一行解決,再不然就是 substr,或者直接用陣列存取 $str[0] ~ $str[3] .. 等等,有沒有簡單又快速的解法呢?

PHP 依照「位置」來快速分割固定格式文字

有固定的格式的字串,要依照格式切割,可以考慮使用 sscanf 來做輸入拆解。

  • 先說結論:sscanf($str, $format, $mixed...) 參數直接於後面吃進來最推薦

sscanf 的範例程式

<?php
$str = '20171110235959';

// 陣列接收
$d = sscanf($str, '%4d%2d%2d%2d%2d%2d');
print_r($d);

// 使用 list() 接收
list($y, $m, $d, $h, $i, $s) = sscanf($str, '%4d%2d%2d%2d%2d%2d');

// 直接於 sscanf() 後面接收
sscanf($str, '%4d%2d%2d%2d%2d%2d', $y, $m, $d, $h, $i, $s); // 同上 list() 一樣結果
?>

preg_match、substr 的範例程式

<?php
$str = '20171110235959';

// preg_match
preg_match('/(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})/', $str, $m);
print_r($m);

// substr
$y = substr($str, 0, 4) . "\n";
$m = substr($str, 4, 2) . "\n";
$d = substr($str, 6, 2) . "\n";
$h = substr($str, 8, 2) . "\n";
$i = substr($str, 10, 2) . "\n";
$s = substr($str, 12, 2) . "\n";

// string
$y = $str[0] . $str[1] . $str[2] . $str[3];
$m = $str[4] . $str[5];
$d = $str[6] . $str[7];
$h = $str[8] . $str[9];
$i = $str[10] . $str[11];
$s = $str[12] . $str[13];
?>

於 PHP 7.0.19 測試 preg_match、substr、sscanf、string 的速度差異

  • preg_match:0.11992454528809 秒
  • substr:0.026941299438477 秒
  • sscanf:0.021934509277344 秒 (註:sscanf 使用 $d 陣列接收)
  • sscanf:0.010013580322266 秒 (註:sscanf 使用 list() 接收)
  • sscanf:0.0059604644775391 秒 (註:sscanf 直接在 function 後面接收)
  • string:0.0050067901611328 秒

雖然 sscanf 沒有比字串陣列存取快,但是寫法簡單易懂,速度也比 substr、regex 的快速(跟 string 也沒差多少),可以參考使用。

註:sscanf 用來 parse access.log 應該也不錯用,於 PHP 官網看到下述範例:

<?php
$line = '123.123.123.123 - - [09/Nov/2017:06:25:10 +0800] "GET /2016/01/linux-find-file-directory-perm-2016/ HTTP/1.1" 200 39239 "-" "Mozilla/5.0 (compatible)"';
$log = [];
$n = sscanf(trim($line), '%s %s %s [%[^]]] "%s %s %[^"]" %d %s "%[^"]" "%[^"]"',
    $log['ip'],
    $log['client'],
    $log['user'],
    $log['time'],
    $log['method'],
    $log['uri'],
    $log['prot'],
    $log['code'],
    $log['bytes'],
    $log['ref'],
    $log['agent']
);
?>

作者: Tsung

對新奇的事物都很有興趣, 喜歡簡單的東西, 過簡單的生活.

發表迴響

這個網站採用 Akismet 服務減少垃圾留言。進一步了解 Akismet 如何處理網站訪客的留言資料