前言:
開發的時候有時需要提取一個長字符串里面的部分字符,常用於變量的查詢、替換等。
場景:
假如我有一個hiveSQL語句,需求為:將變量{@date}替換成具體的日期,如20200526,
select "F" as sex, c.moviename as name, avg(a.rate) as avgrate, count(c.moviename) as total from t_rating a join t_user b on a.userid = b.userid join t_movie c on a.movieid = c.movieid where b.sex = "F" and a.dt = {@date} and b.dt = {@date } group by c.moviename having total >= 50 order by avgrate desc limit 10;
解決思路:
如上SQL里面不同用戶寫{@date}的格式不同,有點用戶寫法存在部分空格如{@date },情況很多,假如我們以此列舉出來很繁瑣,代碼執行效率很低,那么該如何解決呢?這個時候想到的最優解應該是利用強大的正則匹配來解決此類問題;
解決方法:
利用正則檢索的方法,正則為:
$regex = '/\{\s*([\w\W]*?)\s*\}/'; preg_match_all($regex, $sql . " ", $matches); 正則解釋: \s*表示任意的空白符,其中*為匹配前面的子表達式零次或多次,為貪婪模式 *?非貪婪模式,遇到后面的字符后即停止執行 \w :匹配包括下划線的任何單詞字符,等價於 [A-Z a-z 0-9_] \W :匹配任何非單詞字符,等價於 [^A-Z a-z 0-9_]
以上SQL{@date}變量替換日期方法例子如下:
/** * @date日期變量字符串格式化 * @param string $sql * @param bool $date * @return mixed */ public static function dateFormat($sql, $date = false) { //正則取出全部含有@date字符串的{} $regex = '/\{\s*([\w\W]*?)\s*\}/'; preg_match_all($regex, $sql . " ", $matches); if (!empty($matches[0])) { foreach ($matches[0] as $string) { if (stristr($string, '@date')) { //去除字符串空格 $cleanString = str_replace(' ', '', $string); //若傳參$date存在,則替換變量為具體@date值 if ($date) { if ($cleanString == '{@date}') { $cleanString = $date; } $sql = str_replace($string, $cleanString, $sql); } } } } return $sql; }
另外,針對於簡單的單個字符串提取可以使用以下方法:
//提取{}里面的字符串
preg_match('/{.*}/',$sql,$match); echo $match[0];