首先写一个简单的代码做测试
$pattern = '/\bis\b/';
$subject = "this is dog";
if(preg_match_all($pattern, $subject,$matches)){
var_dump($matches);
}else{
echo "false";
}
边界限制
^ 与 $ 可以用来匹配 整个字符串的开始和结束边界
\b 匹配字符串中单词的边界 如空格, \B 则是非单词边界
用上面的例子做测试得到如下结果
array (size=1)
0 => string 'is' (length=2)
html
先写一个html字符串
$subject = '<button class="ff" id="sure" data="ffff">取消</button><button>确定</button><input value="test"/>';
如何匹配到其中的每一个标签呢,期望得到
array (size=3)
0 => '<button class="ff" id="sure" data="ffff">取消</button>'
1 => '<button>确定</button><input value="test"/>'
2 => '<input value="test"/>';
尝试
$pattern = '/<.*>.*<\/.*>/';
得到
array (size=1)
0 => string '<button class="ff" id="sure" data="ffff">取消</button><button>确定</button><input value="test"/>' (length=100)
模式修正符U
结果匹配到了整个字符串, 而不是第一个button标签。
原因是因为 正则默认使用贪婪匹配, 就是会匹配到最长的字符, 本例中正则中的”<\/.>”匹配到了最后的</button><input value="test"/>
, . 匹配到了button><input value="test"/
,关闭贪婪匹配使用模式修正符U, 或者在模式后面使用?
$pattern = '/<.*>.*<\/.*>/U';
$pattern = '/<.*?>.*?<\/.*?>/';
得到
array (size=1)
0 => string '<button class="ff" id="sure" data="ffff">取消</button>' (length=56)
后向引用
现在我们得到了第一个button, 注意到一点我们的html便签中首尾是对应的<button>
对应</button>
而不是 </span>
或者其他
这里我们可以用后向引用
使用元字符”()”标记的原子是一个子表达式, 被匹配的字符会被缓存起来, 供以后使用。 可以使用编号“\1,\2,\3,…”来访问缓冲区的内容
首先用“\w+”匹配标签名, 与 “.*” 可能匹配的标签其他属性区分开
$pattern = '/<(\w+).*>.*<\/\\1>/U';
注意: 是 “\\1” , php字符串使用一个”\”表示转义, 而”\\”才表示反斜线
运行结果为
array (size=2)
0 => string '<button class="ff" id="sure" data="ffff">取消</button>' (length=56)
1 => string 'button' (length=6)
可以看到使用元字符”()”标记的原子所匹配到的字符也被返回, 这对后续的处理也是很有帮助的。
模式选择符(|)
接下来呢我们想匹配后面的第二个button便签和input标签, 这里我们就需要使用php提供的另一个函数 preg_match_all
了
经代码改为
$pattern = '/<(\w+).*>.*<\/\\1>/U';
$subject = '<button class="ff" id="sure" data="ffff">取消</button><button>确定</button><input value="test"/>';
if(preg_match_all($pattern, $subject,$matches)){
var_dump($matches);
}else{
echo "false";
}
运行结果为
array (size=2)
0 =>
array (size=2)
0 => string '<button class="ff" id="sure" data="ffff">取消</button>' (length=56)
1 => string '<button>确定</button>' (length=23)
1 =>
array (size=2)
0 => string 'button' (length=6)
1 => string 'button' (length=6)
这样我们就得到了两个button标签, 为什么没有 input 呢, 因为input 是单标记, 我的正则匹配不到。
单标记也很简单 $pattern = '/<(\w+).*\/>/U';
就可以了, 在使用模式选择符(|)连接这两个正则就可以了。
$pattern = '/<(\w+).*>.*<\/\\1>|<(\w+).*\/>/U';
运行效果就是
array (size=3)
0 =>
array (size=3)
0 => string '<button class="ff" id="sure" data="ffff">取消</button>' (length=56)
1 => string '<button>确定</button>' (length=23)
2 => string '<input value="test"/>' (length=21)
1 =>
array (size=3)
0 => string 'button' (length=6)
1 => string 'button' (length=6)
2 => string '' (length=0)
2 =>
array (size=3)
0 => string '' (length=0)
1 => string '' (length=0)
2 => string 'i' (length=1)
遗留问题
确是得到了三个标签,但是看到最后一个数组,匹配到的是“i”而不是“input”,想想可能还是贪婪匹配的问题,于是我尝试了(\w+?),用问号开启贪婪匹配
$pattern = '/<(\w+).*>.*<\/\\1>|<(\w+?).*\/>/U';
得到了想要的结果
array (size=3)
0 =>
array (size=3)
0 => string '<button class="ff" id="sure" data="ffff">取消</button>' (length=56)
1 => string '<button>确定</button>' (length=23)
2 => string '<input value="test"/>' (length=21)
1 =>
array (size=3)
0 => string 'button' (length=6)
1 => string 'button' (length=6)
2 => string '' (length=0)
2 =>
array (size=3)
0 => string '' (length=0)
1 => string '' (length=0)
2 => string 'input' (length=5)
分析一下可能是因为关闭了贪婪匹配的情况下(\w+)匹配到了i, 就不继续匹配了,而是交给了”.*”, 可是这个问题在匹配button标记的时候并没有呀, 成功的匹配到了’button’而不是’b’, 这也是个遗留的问题希望大神帮我解答。
还有一种解决方法呢就是用到上面提到的边界限制, (\w+\b). 得到了相同的结果
$pattern = '/<(\w+).*>.*<\/\\1>|<(\w+\b).*\/>/U';
还有一个问题是现在得到的数组不是很理想 button, input 被分到了两个数组中, 没有想到好办法只有合并数组
$matches[3] = array_merge(array_filter($matches[1]),array_filter($matches[2]));
得到
array (size=4)
0 =>
array (size=3)
0 => string '<button class="ff" id="sure" data="ffff">取消</button>' (length=56)
1 => string '<button>确定</button>' (length=23)
2 => string '<input value="test"/>' (length=21)
1 =>
array (size=3)
0 => string 'button' (length=6)
1 => string 'button' (length=6)
2 => string '' (length=0)
2 =>
array (size=3)
0 => string '' (length=0)
1 => string '' (length=0)
2 => string 'input' (length=5)
3 =>
array (size=3)
0 => string 'button' (length=6)
1 => string 'button' (length=6)
2 => string 'input' (length=5)
中文匹配
$pattern = '/[^\x{4e00}-\x{9fa5}]+/u'; // utf-8 中文
$pattern = "/[".chr(0xa1)."-".chr(0xff)."]+/"; // gb2312 中文
$pattern = '/[^\x{00}-\x{f0}]+/u'; // utf-8 所有特殊符号, 可以匹配到中文标点