开发的时候有时需要提取一个长字符串里面的部分字符,常用于变量的查询、替换等。

假如我有一个hiveSQL语句,需求为:将变量{@date}替换成具体的日期,如20200526,

select 
  "F" as sex, 
  c.moviename as name, 
  avg(a.rate) as avgrate, 
  count(c.moviename) as total 
  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 

解决思路:

如上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];