我目前正在使用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);
}
}
唯一的问题是我需要检查每个结果索引以确保
<a href='...'>catsup</a>
<a>
<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>'
答案 0 :(得分:1)
这将查找在锚标记之外使用prefex'cat'的所有单词
您需要在regex搜索命令中使用不区分大小写的选项。
(?<=^|<[\/]a>)[^<]*\b(cat\w*|[^<]*?\s\bcat\w*)\b
<?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>)/';