php中带有负lookback的正则表达式
我正在使用preg_replace_回调对大量目录产品描述进行SEO,但在使用regex时遇到了一些困难 我想替换所有这些单词(帽子、衬衫),除了“men's”+0-2个单词之后的单词,例如“men's pretty black hat”,“men's long shirt”不应替换 以下是调试代码,在实际应用程序中,我使用回调为每个单词选择合适的替换:php中带有负lookback的正则表达式,php,regex,Php,Regex,我正在使用preg_replace_回调对大量目录产品描述进行SEO,但在使用regex时遇到了一些困难 我想替换所有这些单词(帽子、衬衫),除了“men's”+0-2个单词之后的单词,例如“men's pretty black hat”,“men's long shirt”不应替换 以下是调试代码,在实际应用程序中,我使用回调为每个单词选择合适的替换: $str = "men's black hat, and orange shirt!"; preg_match_all('/((\s|\.\s
$str = "men's black hat, and orange shirt!";
preg_match_all('/((\s|\.\s|,\s|\!\s|\?\s)(hat|shirt)(\s|\.|\.\s|,\s|\!|\!\s|\?|\?\s))/i', $str, &$_matches);
print_r($_matches);
谢谢我认为可变长度的负面外观是不可能的 一个技巧是反转字符串并使用负lookaheads。那么,您“理想”想要做的是:
preg_match_all('/(?<!\bmen\'s\s+(\w+\s+){0,2})(hat|shirt)\b/i', $str, &$_matches);
然后使用array\u map
反转所有结果
顺便说一下,
\b
被称为单词边界。它们可能是您想要使用的,而不是所有的(\s | \.\s | \.\s | \!s | \!\s | \?| \?\s)
回溯必须是固定长度的,因此这种解决问题的方法不起作用
我知道你想让preg\u relace\u callback
做得太多了。如果您想要执行复杂度超过某个级别的操作,那么放弃单个函数调用的便利性是合理的。以下是解决此问题的另一种方法:
preg\u split
将文本与标记preg\u split\u OFFSET\u CAPTURE
一起拆分为单词,以便知道每个单词在原始文本中的显示位置preg_split
的偏移量和正匹配的(已知)长度来启动原始文本输入$str = "men's black hat, and orange shirt!";
$targets = array('hat', 'shirt');
$shield = 'men\'s';
$bias = 0;
for ($i = 0; $i < count($words); ++$i) {
list ($word, $offset) = $words[$i];
if (!in_array($word, $targets)) {
continue;
}
for ($j = max($i - 2, 0); $j < $i; ++$j) {
if ($words[$j][0] === $shield) {
continue 2;
}
}
$replacement = 'FOO';
$str = substr_replace($str, $replacement, $offset + $bias, strlen($word));
$bias += strlen($replacement) - strlen($word);
}
echo $str;
$str=“男式黑帽子和橙色衬衫!”;
$targets=数组('hat','shirt');
$shield=‘男士’;
$bias=0;
对于($i=0;$i
你能澄清你的问题吗?您谈到了替换,但正在使用
preg\u match\u all
。另外,您希望从您提到的调试代码中得到什么结果?模拟可变长度查找的另一种方法是使用\K
。在遇到\K
之前匹配的任何内容都将被丢弃/“遗忘”,这有效地允许您匹配任何内容,然后仅在\K
之后开始捕获。搜索“重新设置比赛开始”大约在比赛进行到一半时。没问题。我自己更喜欢\@Jon的解决方案,也不知道@Wiseguy的\K
构造。谢谢,关于preg_split()和进一步处理的观点非常好。它只是工作。谢谢,伙计!唯一的问题是,如果替换“FOO”的长度与原始的$word
不同,那么$offset
在第一次迭代后是不正确的=>substr\u replace会弄乱原始文本:)我用$offsetCorrection+=(strlen($replacement)-strlen($word))
@c0rewell:Yup解决了这个问题,这绝对是一个错误,我真的应该抓住它。谢谢你的反馈,我相应地修正了答案。
$str = "men's black hat, and orange shirt!";
$targets = array('hat', 'shirt');
$shield = 'men\'s';
$bias = 0;
for ($i = 0; $i < count($words); ++$i) {
list ($word, $offset) = $words[$i];
if (!in_array($word, $targets)) {
continue;
}
for ($j = max($i - 2, 0); $j < $i; ++$j) {
if ($words[$j][0] === $shield) {
continue 2;
}
}
$replacement = 'FOO';
$str = substr_replace($str, $replacement, $offset + $bias, strlen($word));
$bias += strlen($replacement) - strlen($word);
}
echo $str;