删除 PHP 字符串中最后一次出现的非连续重复 word/phase

Delete last occurrence of a non-consecutive, duplicate word/phase in a PHP string

好吧,我想弄清楚这个问题已经有一段时间了,但我似乎无法弄清楚。我需要从 END[=54 中删除 last 一个不连续的、重复的 word/phrase =] 的字符串。例如,我想要

Love in My Antonia Love in

Love in My Antonia Love

成为

Love in My Antonia

我尝试了无数种模式都没有成功。我最接近成功的是:

 preg_replace('/\b(\w{2,})\b(?=.*?\1)\W*/', ''

这将删除 第一次 出现(而不是最后一次),呈现:

 in My Antonia Love (ORIGINAL: "Love in My Antonia Love")

 My Antonia Love in (ORIGINAL: "Love in My Antonia Love in")

请帮忙! :)



更新(11 月 9 日,2:00 下午,太平洋标准时间):我应该澄清的是——如果可能的话——我希望解决方案保持我在示例中展示的简单、单行、紧凑的格式:

preg_replace('/\b(\w{2,})\b(?=.*?\1)\W*/', ''

我的示例几乎可以完美运行,只是它删除了 first 匹配而不是 last。我希望有人可以适度地操纵我现有的代码,以便它删除最后一个匹配项(在字符串的末尾)而不是第一个匹配项。是不是比我想象的要复杂?



以前,我想出了一个版本,可以在字符串中的任意位置找到两个连续的重复 words/phrases 并将它们替换为一个:

preg_replace('~\b([\S \w]{3,})\K\b(?:\s*)+~', '', 

这使得 "pizza pizza" 变为 "pizza" 并且 "I walked to the store I walked to the store" 变为 "I walked to the store." 太棒了,我已经采用了该解决方案。现在,其次,我还需要 "Pizza is the best pizza" 变成 "Pizza is the best." 同样,"Sheep dogs are awesome pets dogs are" 应该变成 "Sheep dogs are awesome pets." 所以,基本上,第一次出现在字符串中的什么地方并不重要;重要的是 END OF THE STRING 处的事件被删除。我希望这能带来更多清晰度。

您可以在没有正则表达式的情况下解决这个问题,方法是将句子拆分为组成词,然后手动检查最后两个词:

$input = "Love in My Antonia Love in";
$words = preg_split("/\s+/", $input);
$last = $words[count($words)-1];
$pattern = "/^(?=.*\b" . $last . "\b.*\b" . $last . "\b).*/";
if ($words[count($words) - 1] != $words[count($words) - 2] &&
    preg_match($pattern, $input, $match)) {
    array_pop($words);
}
$output = implode(" ", $words);
echo $input . "\n" . $output;

Love in My Antonia Love in
Love in My Antonia Love

您需要先找到最长的重复子串,然后将其从主题串的末尾移除。这可以使用 preg_match_all 进行不区分大小写的搜索然后使用 preg_replace 省略它们来完成:

$str = 'Love in My Antonia Love in';
preg_match_all('~(\b\w++(?> \w++)*)(?=.*?\b)~i', $str, $matches);
$array = array_unique(array_map('strtolower', $matches[1]));
foreach ($array as $value) {
    $str = preg_replace("~^.*\K(?<!\s)\s*\b$value~i", '', $str);
}
echo trim($str); // Love in My Antonia

live demo here

给你:

$s = preg_replace('/^\b([\w ]+)(.*?)\b()$/i', '\1\2', $s);

测试:

$s = "Love in My Antonia Love in";
$s1 = "Love in My Antonia Love";
$s2 = "Love in My Antonia Love Not On End";

echo "Original:\n$s\n";
echo preg_replace('/^\b([\w ]+)(.*?)\b()$/i', '\1\2', $s);
echo "\n";
echo "Original:\n$s1\n";
echo preg_replace('/^\b([\w ]+)(.*?)\b()$/i', '\1\2', $s1);
echo "\n";
echo "Original:\n$s2\n";
echo preg_replace('/^\b([\w ]+)(.*?)\b()$/i', '\1\2', $s2);

输出:

ZC-MGMT-04:~ jv$ php -q c.php
Original:
Love in My Antonia Love in
Love in My Antonia
Original:
Love in My Antonia Love
Love in My Antonia
Original:
Love in My Antonia Love Not On End
Love in My Antonia Love Not On End

====

更新:

Jason 建议对单词末尾的地址 ' 进行轻微更新:

preg_replace('/^\b([\w ]+)(.*?)\b\b()(\'s)*\b$/i', '\1\2')