代码之家  ›  专栏  ›  技术社区  ›  jerrygarciuh

regex问题:将此模式与硬引号或软引号匹配

  •  0
  • jerrygarciuh  · 技术社区  · 16 年前

    我有一个锚定位regex工作得很好:

    $p = '%<a.*\s+name="(.*)"\s*>(?:.*)</a>%im';
    

    它匹配 <a 后面跟零个或多个任何东西,后面跟一个空格,然后 name="

    它正在获取名称,即使类或ID在锚定中的名称之前。

    我想补充一点,那就是 name=' 从早晚有人会用单引号(“)来完成这项工作。

    显然,我可以为这个添加第二个regex,但它看起来不漂亮。

    有人知道如何添加单引号并只使用一个regex吗?任何其他改进或建议都将非常受欢迎。我可以用我能得到的所有regex帮助!

    非常感谢你的阅读,

    function findAnchors($html) {
        $names = array();
        $p = '%<a.*\s+name="(.*)"\s*>(?:.*)</a>%im';
        $t = preg_match_all($p, $html, $matches, PREG_SET_ORDER);
        if ($matches) {
            foreach ($matches as $m) {
                $names[] = $m[1];
            }
            return $names;
        }
    }
    
    5 回复  |  直到 13 年前
        1
  •  1
  •   Gumbo    16 年前

    试试这个:

    /<a(?:\s+(?!name)[^"'>]+(?:"[^"]*"|'[^']*')?)*\s+name=("[^"]*"|'[^']*')\s*>/im
    

    这里你只需要去掉周围的引号:

    substr($match[1], 1, -1)
    

    但是使用真正的解析器 DOMDocument 当然,这种正则表达式方法会更好。

        2
  •  2
  •   Shawn Biddle    16 年前

    詹姆斯的评论实际上是一个非常流行的,但错误的正则表达式用于字符串匹配。这是错误的,因为它不允许转义字符串分隔符。假定字符串分隔符为“或”以下regex works

    $regex = '([\'"])(.*?)(.{0,2})(?<![^\\\]\\\)(\1)';
    

    \ 1是起始分隔符,2是内容(减去2个字符),3是最后2个字符和结束分隔符。只要转义字符是\且转义字符没有转义,此regex就允许转义分隔符。也就是说,

    'Valid'
    'Valid \' String'
    'Invalid ' String'
    'Invalid \\' String'
    
        3
  •  1
  •   James Emerton    16 年前

    使用 [] 要匹配字符集:

    $p = "%<a.*\s+name=['\"](.*)['\"]\s*>(?:.*)</a>%im";
    
        4
  •  1
  •   pelms    16 年前

    您当前的解决方案不会将锚与“name”后面的其他属性(例如 <a name="foo" id="foo"> )

    尝试:

    $regex = '%<a\s+\S*\s*name=["']([^"']+)["']%i'; 
    

    这将把“name”属性的内容提取到后面的引用中 $1 .
    这个 \s* 也允许属性之间换行。
    你不需要完成剩下的 a '标记为否定字符类 [^"']+ 会懒惰的。

        5
  •  1
  •   Alan Moore Chris Ballance    13 年前

    另一种方法是:

    $rgx='~<a(?:\s+(?>name()|\w+)=(?|"([^"]*)"|\'([^\']*)\'))+?\1~i';
    

    我知道这个问题由来已久,但当它刚刚重新出现时,我想到了另一种用法,即 Cookbook .第一个非捕获组在不情愿的加号控制下处理所有“name=value”对的匹配。( +? )如果属性名是字面上的 name ,空组( () )不匹配,然后返回引用( \1 )再也不匹配了,跳出了循环。(返回引用成功,因为组 参加了比赛 ,即使它不消耗任何字符。)

    每次在组2中捕获属性值,覆盖在上一次迭代中捕获的内容。(分支重置构造( (?|(...)|(...)) 使我们能够“重用”组2来捕获引号内的值,无论它们是哪种引号。)因为循环在名称后退出 名称 最后,最终捕获的值对应于该属性。

    See a demo on Ideone

    推荐文章