Заменить вхождения определенного слова, если оно не повторяется другим конкретным словом?
У меня есть такой текст, как:
*open* blah blah blah blah blah *close* blah blah *open* blah blah *close* blah blah *close*
Мне было интересно, как бы я удалить / заменить любые случаи *close*
которые не продолжаются *open*
,
Таким образом, приведенный выше текст станет:
*open* blah blah blah blah blah *close* blah blah *open* blah blah *close* blah blah
Возможно, я использую регулярное выражение с preg_replace - но мои навыки регулярных выражений не так сильны?
<?php
$string = "*open* blah blah blah blah blah *close* blah blah *open* blah blah *close* blah blah *close*";
$string = preg_replace('#(?<!\*open\*)\*close\*#', '', $string); //this only works for immediate proceedings
echo($string);
?>
Примеры кода будут приветствоваться.
2 ответа
Решение
Это можно сделать без регулярных выражений с помощью следующего кода:
$openTag = '*open*';
$closeTag = '*close*';
$openTagLength = mb_strlen($openTag);
$closeTagLength = mb_strlen($closeTag);
$subj = '*open* blah blah blah blah blah *close* blah blah *open* blah blah *close* blah blah *close*';
$len = mb_strlen($subj);
$isOpened = false;
$res = '';
for ($i = 0; $i < $len; )
{
if (mb_substr($subj, $i, $openTagLength) === $openTag) {
// found open tag
$res .= $openTag;
$isOpened = true;
$i += $openTagLength;
} elseif (mb_substr($subj, $i, $closeTagLength) === $closeTag) {
// found close tag
if ($isOpened) {
$res .= $closeTag;
} // else skip
$isOpened = false;
$i += $closeTagLength;
} else {
// non-tag
$res .= mb_substr($subj, $i, 1);
$i++;
}
}
echo $res;
Попробуйте это:
$pattern = "/(\\*open\\*.*?\\*close\\*)/";
$target = "*close* *close* *open* blah blah blah blah blah *close* blah blah *open* blah blah *close* blah blah *close* *close* *open* *open* *close* ";
$prevMatchEndIndex = 0;
$matches = array();
$lastMatchEndIndex = 0;
$resultParts = array();
while(preg_match($pattern, $target, $matches, PREG_OFFSET_CAPTURE, $prevMatchEndIndex)) {
$matchedString = $matches[0][0];
$matchStartIndex = $matches[0][1];
$matchEndIndex = $matchStartIndex + strlen($matchedString) + 1;
$unmatchedString = substr($target, $prevMatchEndIndex, $matchStartIndex - $prevMatchEndIndex);
$unmatchedString = preg_replace("/\\s*\\*close\\*\\s*/", " ", $unmatchedString);
$resultParts[] = trim($unmatchedString);
$resultParts[] = trim($matchedString);
$prevMatchEndIndex = $matchEndIndex;
$lastMatchEndIndex = $matchEndIndex;
}
$lastUnmatchedPart = substr($target, $lastMatchEndIndex);
$lastUnmatchedPart = preg_replace("/\\s*\\*close\\*\\s*/", " ", $lastUnmatchedPart);
$resultParts[] = $lastUnmatchedPart;
echo $target . "<br />";
echo join($resultParts, " ");