PHP удалить (условно) повторяющуюся строку в тексте

$string = "Apple
Foo
Banana
...
Banana
Foo
Other text
...
Apple";

У меня есть текст, в котором отдельные строки дублируются после строки "...".

Строки до и после этого могут быть любыми («Foo»), но также могут быть дубликатами (без «...», например «Apple»).

Строка "..." может появляться несколько раз без повторяющейся строки после нее.

Я хочу удалить только повторяющиеся строки, между которыми есть строка "...".

Другими словами: удалите строку после "...", если она такая же, как выше "..."

Как я могу соответствовать

Banana
...
Banana

чтобы удалить повторяющуюся строку:

Banana

так что результат

$string = "Apple
Foo
Banana
...
Foo
Other text
...
Apple";

Ваше здоровье!


person Martin    schedule 04.06.2012    source источник
comment
что ты сделал до сих пор? У вас есть код, с которого можно начать?   -  person Eineki    schedule 04.06.2012
comment
Foo по-прежнему появляется дважды   -  person Ja͢ck    schedule 04.06.2012
comment
Теперь здесь больше нет шансов, я знал, что скоро придут люди, которые любят What have you tried, и в эти дни здесь нечему вас чему-то научить.   -  person Sarfraz    schedule 04.06.2012
comment
Вы хотите удалить все, что повторяется после ... строки? Нравится или копия должна быть прямо над и под ним? Повторы появляются только после ... строки?   -  person Raekye    schedule 04.06.2012
comment
Строку с... и следующую строку надо убрать? Это оно?   -  person Ja͢ck    schedule 04.06.2012
comment
Только строка после... если она такая же, как выше...   -  person Martin    schedule 04.06.2012
comment
возможный дубликат удалить дубликат из строки в PHP   -  person Emil Vikström    schedule 04.06.2012
comment
Никакого обмана, поскольку array_unique() здесь не применяется.   -  person Martin    schedule 04.06.2012


Ответы (4)


Если задача состоит в том, чтобы просто удалить строку, следующую за строкой с тремя точками:

echo preg_replace("/^(.+?)\r?\n(\.{3})\r?\n\\1/m", "\\1\n\\2", $string);

Выражение соответствует:

  • целая строка, содержащая хотя бы один символ (1)
  • три точки на одной линии (2)
  • целая строка, содержащая хотя бы один символ (1)

Модификатор /m используется для выбора многострочного режима, в котором ^ и $ несут значение начала и конца строки.

Обратная ссылка \\1 используется для соответствия тому, что было до трех точек.

Замена '\\1' необходима, чтобы вернуть совпавшую линию с тремя точками.

person Ja͢ck    schedule 04.06.2012
comment
Отредактировал ответ, чтобы поместить ... обратно в окончательную строку. - person Ja͢ck; 04.06.2012
comment
Извините, ...-строка может появляться несколько раз без повторяющихся строк. - person Martin; 04.06.2012
comment
@Мартин видел, что вы выбрали другой ответ как принятый. Мой ответ не сработал для вас? - person Ja͢ck; 05.06.2012
comment
@Martin, вау, это действительно странно, я проверил это локально, прежде чем публиковать, и это сработало, но кажется, что после ... и перед маркером конца строки есть пробелы ... странно ... обновленный ответ - person Ja͢ck; 05.06.2012
comment
@Martin Мартин а, конечно, новые строки Windows =p радости регулярных выражений - person Ja͢ck; 05.06.2012
comment
Ой! Работает сейчас и намного легче, чем грубая сила. Спасибо :) - person Martin; 06.06.2012

Вот как можно удалить повторяющиеся строки в строке:

$string = implode( "\n", array_unique( explode( "\n", $string)));

explode() строку в массив на новой строке, вызовите array_unique() в результирующем массиве и соедините строку вместе с implode() .

Вывод:

Text row A
Foo
Text row B
...
Text row C

Однако обратите внимание, что результат не полностью соответствует желаемому результату, поскольку желаемый результат противоречит вашему определению проблемы.

Демо

person nickb    schedule 04.06.2012
comment
Извините, мой пример был недостаточно ясен. Я хочу удалить только повторяющиеся строки, между которыми есть ... строка. - person Martin; 04.06.2012

Я не уверен, что понимаю все условия (можно ли дублировать перед ... например), но как насчет $string = implode("\n", array_unique(explode("\n", $string)));

Обновить Решение грубой силы:

$string = "Apple\nFoo\nBanana\n...\nBanana\nFoo\nOther text\n...\nApple\n";
$string2 = "";

$arr = explode("\n", $string);

$string2 .= $arr[0] . "\n";
$string2 .= $arr[1] . "\n";

for ($i=2; $i<count($arr); $i++)
{
    if ($arr[$i-1] != '...' || $arr[$i-2] != $arr[$i])
    {
        $string2 .= $arr[$i] . "\n";
    }

}

echo $string2;
person danneth    schedule 04.06.2012
comment
Обновлен с помощью решения грубой силы (хотя я уверен, что есть удобный способ RegExp решить эту проблему) - person danneth; 04.06.2012
comment
Добро пожаловать! Вероятно, вам следует проверить, что explode возвращает два элемента, прежде чем слепо добавлять их в строку. В противном случае вы получите странные результаты, если входная строка пуста (или не содержит новых строк). - person danneth; 05.06.2012

person    schedule
comment
Это также удаляет второй Foo, я думаю, что ОП хочет что-то еще. - person Ja͢ck; 04.06.2012