删除PHP字符串中最后一次出现的非连续重复单词/阶段

时间:2018-11-09 10:42:51

标签: php regex preg-replace

好的,我已经尝试了一段时间,但是我似乎无法正确地做到这一点。我需要从字符串的 END 中删除 last 个不连续的重复单词/短语。例如,我要

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 PM):我应该澄清-如果可能的话-我希望解决方案保持在示例中显示的简单的1行紧凑格式中: / p>

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

我的示例已经非常完美地工作了,只是它删除了 first 匹配项而不是 last 匹配项。我希望有人可以适度地操纵我现有的代码,以便它删除最后一个匹配项(在字符串的末尾)而不是第一个匹配项。那比我想的还要复杂吗?



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

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

这使“比萨饼披萨”成为“比萨饼”,“我去商店的我走到商店”变成“我去商店的”。太好了,我已经合并了该解决方案。现在,第二,我还需要“披萨是最好的披萨”才能成为“披萨是最好的”。同样,“牧羊犬是很棒的宠物狗”应该变成“牧羊犬是很棒的宠物”。因此,基本上,第一次出现在字符串中的位置无关紧要;重要的是的出现被删除了。我希望这会带来更多的清晰度。

3 个答案:

答案 0 :(得分:1)

您可以在不使用正则表达式的情况下进行处理,方法是将句子拆分为组成词,然后手动检查最后两个词:

$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

答案 1 :(得分:1)

您在这里:

$s = preg_replace('/^\b([\w ]+)(.*?)\b(\1)$/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(\1)$/i', '\\1\\2', $s);
echo "\n";
echo "Original:\n$s1\n";
echo preg_replace('/^\b([\w ]+)(.*?)\b(\1)$/i', '\\1\\2', $s1);
echo "\n";
echo "Original:\n$s2\n";
echo preg_replace('/^\b([\w ]+)(.*?)\b(\1)$/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(\1)(\'s)*\b$/i', '\\1\\2')

答案 2 :(得分:0)

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

$str = 'Love in My Antonia Love in';
preg_match_all('~(\b\w++(?> \w++)*)(?=.*?\b\1)~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