确定html字符串中的位置是否在锚标记内

时间:2013-05-22 15:05:15

标签: php html regex preg-match-all

我目前正在使用preg_match_all()查找以特定前缀开头的所有单词。例如,如果前缀为cat,则catsup将被视为匹配,而housecat则不会。

一旦找到这些实例及其偏移量,我就会循环使用它们并基本上用锚标记封装它们。

(问题继续下面的代码)


//Escape all non-standard characters
$preffix = sanitizePreffix($part['modlnoPreffix']);

//All Words Starting with preffix string
$pattern = "/".$preffix.'/'; 

//Find Matches
preg_match_all($pattern , $item['body'], $matches,PREG_OFFSET_CAPTURE);
$matches = array_reverse($matches[0]);

if (count($matches)>0){
    foreach ($matches as $match){
        $text = $match[0];
        $offset = (int)$match[1];
        $endOffset = $offset + strlen($text);
        $url = "/specsheet_getPreffixParts.php?m=".urlencode($text);

        //Insert ending </a> Tag                    
        $item['body'] = str_insert('</a>', $item['body'], $endOffset);

        //Insert Starting <a ...> Tag
        $item['body'] = str_insert("<a rel='".$url."' href='javascript:void(0);'>", $item['body'], $offset);
    }
}

唯一的问题是我需要检查每个结果索引以确保

  1. 结果已经链接到<a href='...'>catsup</a>
  2. <a>
  3. 的起始<a href='/part/catsup'> ... </a>标记内,结果为

    我确信我可以轻松创建一个函数,一次向后搜索一个字符,搜索<a,然后一次向前查找一个字符,寻找</a>,但这似乎是对我有点傻。

    我的问题是:有更好的方法吗?我最初的直觉是使preg_match_all使用的初始搜索模式的这一部分 - 换句话说....

    我将如何find all words that start with 'cat' but are not located between a '<a' and a '</a>'

2 个答案:

答案 0 :(得分:1)

描述

这将查找在锚标记之外使用prefex'cat'的所有单词

您需要在regex搜索命令中使用不区分大小写的选项。

(?<=^|<[\/]a>)[^<]*\b(cat\w*|[^<]*?\s\bcat\w*)\b

enter image description here

正则表达式的PHP示例

 <?php
$sourcestring="CatSoup<a href='...'>catsup</a>catfish tag itself like <a href='/part/catsup'> ... </a>";
preg_match_all('/(?<=^|<[\/]a>)[^<]*\b(cat\w*|[^<]*?\s\bcat\w*)\b/i',$sourcestring,$matches);
echo "<pre>".print_r($matches,true);
?>

$matches Array:
(
    [0] => Array
        (
            [0] => CatSoup
            [1] => catfish
        )

    [1] => Array
        (
            [0] => CatSoup
            [1] => catfish
        )

)

要捕获字符串中的位置,您需要使用标志PREG_OFFSET_CAPTURE,但我不确定如何从数组中提取该值。 preg_match_all('/<a\b[^>]*>(cat\w*|[^<]*?\s\bcat\w*)/i',$sourcestring,$matches, PREG_OFFSET_CAPTURE);

声明

首先应该使用html解析引擎拉出内部文本,这样可以避免在解析HTML文本的正则表达式失败时出现问题的边缘情况。但是我在OP的评论中看到你控制了HTML并且它是相当基本的,所以这个免责声明可能不适用。

答案 1 :(得分:1)

我不同意使用解析器的建议不一定适用于此问题。我肯定会这样说,看起来你可能正在处理足够的结构复杂性,使正则表达式方法不可行。

然而,假设您实际上正在处理要由正则表达式解析的基本足够的HTML语法子集,那么我注意到在给出的示例中,您可以只查找<\a>来跟踪匹配的字符串,如果出现匹配则拒绝匹配,这可以通过简单的前瞻来完成,例如:

$pattern = "/".$preffix.'(?!.*<\/a>)/';

或者,为了确保前瞻只看下一个看到的标签,

$pattern = "/".$preffix.'(?![^<]*<\/a>)/';