正则表达式
正则表达式
php中的正则表达式,有几个已preg开头的函数。
语法
preg_match
进行匹配,匹配到一个结果就行了。个人感觉,跟str_replace替换的参数顺序差不多。
该函数有返回值,返回0或1。其中,第3个参数,用来接收返匹配结果值的。如果不需要,则可以省略。
preg_match_all
同preg_match,但是在匹配到第一个结果后,还会接着匹配后续的。
preg_split
可以进行分隔。比如不规则的csv文件,则可以使用这个符号来进行分隔。用法类似与explode。
上面的这些函数,其实都需要正则表达式的pattern参数。则该参数,是用字符来表达的。所以,可能有下面两种形式:
"/正则表达式/"
'/正则表达式/'
$p1="/<tr class=\".*?>.*?<\/tr>/"
$p2='/<tr class=".*?>.*?<\/tr>/'
但是差别还是挺大的,因为两中字符串内的转义符号支持情况不同。p1跟p2其实想表达的是同一个意思,但是,双引号内,需要对部分内容进行转义,结果更复杂一些。
php语法里面支持转义,而正则表达式里面也有一些类似转义的符号,两者肯定会打架。我记得表示是用r前缀来减少二者的叠加。
所以,我觉得,如果想正则表达式简单一些,能用单引号,尽量用。
场景1:
为了解析html文件中的table,但是手里面又懒得找相关的dom解析工具。所以,选择了功能强大的正则表达式。
匹配tr标签如下:
public static function tr($text){
preg_match_all('/<tr class=".*?>(.*?)<\/tr>/',$text,$result);
return $result[1];
}
说明:
.*?其实是为了避免贪婪匹配。如'/<tr class=".*>,进行了贪婪匹配,匹配到最大的行。本来有10个结果,未进行限制,则贪婪匹配,结果只有一个。(.*?)使用了括号表达式。正因为使用括号,匹配到的结果,放到了$result[1]。\/本意是想使用斜杆,但是由于跟正则表达式原有的有冲突,需要用反斜杆进行转义。- 在测试正则表达式的过程中,可以写一段,试一段结果。
匹配td标签如下:
其中增加了一个map函数。
public static function td($text){
preg_match_all('/<td.*?>(.*?)<\/td>/',$text,$result);
return array_map('trim',$result[1]);
}
另外,由于table又比较多,我又懒得用正则匹配,所以使用了substr,多行文本效果不好,我又进行了替换:
替换掉换行符号(我测试的例子,居然有两种格式),如果不替换,则也出不来结果。我猜测句号点,好像不包括换行符号。然后我测试使用 [.|\n|\r\n]来代替原有的点,好像也不行。单、双引号也试过了。
能不用替换换行符就能替换的方法,我还没有找到。
//从 class="EOS_table"> 开始截取
$find = strpos($cont,'class="EOS_table">');
$cont = substr($cont,$find,-1);
//多行文本,正则好像不能很好的识别
$cont = strtr($cont,["\r\n"=>'',"\n"=>'']);
场景2:
利用正则,忽略不是纯单号的运单。如果没有,则返回空结果。
// 去掉运单号中的字母。
$mailnoMatch=[];
\preg_match('/\d+/',$mailno,$mailnoMatch);
if(!count($mailnoMatch)){
Log::log('redis内的单号格式不正确 '.$record ."\n");
continue;
}
延伸
通过前面的table解析成二维数组的方式,我觉得,作为一个程序员,需要掌握这种基础的表达结果。是那种刻到脑子里面的那种。具体参见 array.md。