php正则表达式的小点心

首先写一个简单的代码做测试

$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 所有特殊符号, 可以匹配到中文标点
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值