sonra (PHP ve JS kullanarak) bazı metni değiştirmek HTMLformat tutmak

6 Cevap php

Ben gibi HTML değiştirmek istiyorum

I am <b>Sadi, novice</b> programmer.

karşı

I am <b>Sadi, learner</b> programmer.

Bunu yapmak için ben bir dize "novice programmer" kullanarak arama yapar. Ben bunu nasıl yapabilirim lütfen? Herhangi bir fikir?

Birden fazla kelime "acemi programcı" kullanarak arama. Bu bir bütün cümle olabilir. Fazladan beyaz boşluk (örneğin yeni satır, sekme) göz ardı edilmelidir ve herhangi bir etiket arama sırasında dikkate alınmalıdır. Fakat etiket değiştirme sırasında korunmalıdır.

Bu dönüştürücü bir tür. O case insensitive ise daha iyi olacaktır.

Teşekkür ederim

Sadi


More clarification:

Ben olası bir çözüm ile bazı güzel bir cevap olsun. Aklınızda herhangi bir fikrim yok ama eğer ilanıyla tutmak lütfen.

I would like karşı more clarify the problem just in case anyone missed it. Main post shows the problem as an example scenario.

1) Şimdi sorun find and replace some string without considering the tags. Etiketleri tek bir kelime içinde kendini gösterir. Dizesi birden çok kelime içerebilir. Tag only appear in the content string or the document. The search phrase never contain any tags.

Biz kolayca tüm etiketleri kaldırmak ve bazı metin işlemi yapabilirsiniz. Ama burada başka bir sorun gösterir.

2) The tags must be preserve, hatta metni değiştirdikten sonra. Bu örnekte gösterildiği budur.

Teşekkür ederim Again for helping

6 Cevap

ok i bu ne istediğiniz olduğunu düşünüyorum. Sizin girdi arama alır ve değiştirme, boşlukla ayrılmış dizeleri diziler içine böler, boşluk / html etiketleri herhangi bir sayı ile giriş cümle bulur regexpi oluşturur ve kelimeler arasındaki yerini aynı etiketleri ile yedek cümle ile değiştirir .

arama cümlenin wordCount yerine daha yüksek ise, sadece herhangi bir ekstra kelimeler arasında boşluk kullanır ve yedek wordCount arayışı daha yüksek ise, o ucunda tüm 'yetim' etiketleri katacak. o da find in sıradanifade karakter kolları ve değiştirin.

<?php
function htmlFriendlySearchAndReplace($find, $replace, $subject) {
    $findWords = explode(" ", $find);
    $replaceWords = explode(" ", $replace);

    $findRegexp = "/";
    for ($i = 0; $i < count($findWords); $i++) {
        $findRegexp .= preg_replace("/([\\$\\^\\|\\.\\+\\*\\?\\(\\)\\[\\]\\{\\}\\\\\\-])/", "\\\\$1", $findWords[$i]);
        if ($i < count($findWords) - 1) {
            $findRegexp .= "(\s?(?:<[^>]*>)?\s(?:<[^>]*>)?)";
        }
    }
    $findRegexp .= "/i";

    $replaceRegexp = "";
    for ($i = 0; $i < count($findWords) || $i < count($replaceWords); $i++) {
        if ($i < count($replaceWords)) {
            $replaceRegexp .= str_replace("$", "\\$", $replaceWords[$i]);
        }
        if ($i < count($findWords) - 1) {
            $replaceRegexp .= "$" . ($i + 1);
        } else {
            if ($i < count($replaceWords) - 1) {
                $replaceRegexp .= " ";
            }
        }
    }

    return preg_replace($findRegexp, $replaceRegexp, $subject);
}
?>

burada birkaç testlerin sonuçları:

Original : <b>Novice Programmer</b>
Search : Novice Programmer
Replace : Advanced Programmer
Result : <b>Advanced Programmer</b>

Original : Hi, <b>Novice Programmer</b>
Search : Novice Programmer
Replace : Advanced Programmer
Result : Hi, <b>Advanced Programmer</b>

Original : I am not a <b>Novice</b> Programmer
Search : Novice Programmer
Replace : Advanced Programmer
Result : I am not a <b>Advanced</b> Programmer

Original : Novice <b>Programmer</b> in the house
Search : Novice Programmer
Replace : Advanced Programmer
Result : Advanced <b>Programmer</b> in the house

Original : <i>I am not a <b>Novice</b> Programmer</i>
Search : Novice Programmer
Replace : Advanced Programmer
Result : <i>I am not a <b>Advanced</b> Programmer</i>

Original : I am not a <b><i>Novice</i> Programmer</b> any more
Search : Novice Programmer
Replace : Advanced Programmer
Result : I am not a <b><i>Advanced</i> Programmer</b> any more

Original : I am not a <b><i>Novice</i></b> Programmer any more
Search : Novice Programmer
Replace : Advanced Programmer
Result : I am not a <b><i>Advanced</i></b> Programmer any more

Original : I am not a Novice<b> <i> </i></b> Programmer any more
Search : Novice Programmer
Replace : Advanced Programmer
Result : I am not a Advanced<b> <i> </i></b> Programmer any more

Original : I am not a Novice <b><i> </i></b> Programmer any more
Search : Novice Programmer
Replace : Advanced Programmer
Result : I am not a Advanced <b><i> </i></b> Programmer any more

Original : <i>I am a <b>Novice</b> Programmer</i> too, now
Search : Novice Programmer too
Replace : Advanced Programmer
Result : <i>I am a <b>Advanced</b> Programmer</i> , now

Original : <i>I am a <b>Novice</b> Programmer</i>, now
Search : Novice Programmer
Replace : Advanced Programmer Too
Result : <i>I am a <b>Advanced</b> Programmer Too</i>, now

Original : <i>I make <b>No money</b>, now</i>
Search : No money
Replace : Mucho$1 Dollar$
Result : <i>I make <b>Mucho$1 Dollar$</b>, now</i>

Original : <i>I like regexp, you can do [A-Z]</i>
Search : [A-Z]
Replace : [Z-A]
Result : <i>I like regexp, you can do [Z-A]</i>

Ben bunu istiyorum:

if (preg_match('/(.*)novice((?:<.*>)?\s(?:<.*>)?programmer.*)/',$inString,$attributes) {
  $inString = $attributes[1].'learner'.$attributes[2];
}

Bu, aşağıdakilerden birini uygun olmalıdır:

novice programmer
novice</b> programmer
novice </b>programmer
novice<span> programmer

Regex devletler gibi bir şey olurdu ne bir test versiyonu: "acemi" ulaşmak ve bir yakalama gruba koymak kadar herhangi bir karakter kümesi Maç, sonra belki bir '<' ile başlar şey eşleşmesi ve ondan sonra herhangi sayıda karakter vardır ve sonra (ama onu yakalamak değil) '>' ile biten, ama sonra orada sadece beyaz bir boşlukla şey maç ve sonra belki yeniden bir '<' ile başlar şey eşleşmesi ve ondan sonra herhangi sayıda karakter vardır ve ardından '>' ile biten (ama onu yakalamak değil) daha sonra herhangi bir karakter sayıyla programcı tarafından takip ve yakalama grup içine koymak gerekir hangi.

Ben bazı şeyleri kaçırmış olabilir gibi ben olsa bazı özel testler yapardı. Regex programcılar en iyi arkadaşım!

Peki, orada daha iyi bir yol olabilir, ama kafamın üst kapalı olabilir (etiketleri kelimelerin ortasında görünür olmayacağını varsayarak, HTML vb, iyi biçimlendirilmiş olan) ...

Essentially, you'll need three things (sorry if this sounds patronising, not intended that way): 1. A method of sub-string matching that ignores tags. 2. A way of making the replacement preserving the tags. 3. A way of putting it all together.

1 - Bu, muhtemelen en zor biraz. Bir yöntem, kaynak dize tüm karakterleri (bunlar dizi elemanları sanki karakterleri erişebilirsiniz böylece dizeleri temelde karakter dizileri vardır), durdurma, arama dizesi mümkün olduğunca çok karakter maç çalışırken yoluyla yineleme olacaktır ya karakterlerin tüm eşleşmiş veya maç karakter tükendi zaman. Arasında da dahil olmak üzere '<' herhangi bir karakter ve '>' göz ardı edilmelidir. Bazı sözde kodu (over, geç oldu ve hatalar olabilir bunu kontrol):

findMatch(startingPos : integer, subject : string, searchString : string){
    //Variables for keeping track of characters matched, positions, etc.
    inTag = false;
    matchFound = false;
    matchedCharacters = 0;
    matchStart = 0;
    matchEnd = 0;

    for(i from startingPos to length(searchString)){
        //Work out when entering or exiting tags, ignore tag contents
        if(subject[i] == '<' || subject[i] == '>'){
            inTag = !inTag;
        }
        else if(!inTag){
            //Check if the character matches expected in search string
            if(subject[i] == searchString[matchedCharacters]){
                if(!matchFound){
                    matchFound = true;
                    matchStart = i;
                }
                matchedCharacters++;

                //If all of the characters have been matched, return the start and end positions of the substring
                if(matchedCharacters + 1 == length(searchString)){
                    matchEnd = i - matchStart;
                    return matchStart, matchEnd;
                }
            }
            else{
                //Reset counts if not found
                matchFound = false;
                matchCharacters = 0;
            }
        }
    }
    //If no full matches were found, return error
    return -1;
}

2 - Eğer (eşleşen işlevi tarafından döndürülen iki pozisyon arasında) ve parça önce ve sonra üzerinde çalışmak istediğiniz bit - üç dizeleri içine HTML kaynak kodunu Böl. Örneğin, kullanarak değiştirmek istediğiniz bit kadar bölünmüş:

$parts = preg_split("/(<[^>]*>)/",$string, -1, PREG_SPLIT_DELIM_CAPTURE);

, Etiketleri nerede bir kaydını tutun olmayan etiket kesimleri birleştirmek ve substring, normal olarak, bu üzerinde değiştirme işlemi, sonra tekrar değiştirilmiş bir dize bölmek ve yerine etiketleri ile yeniden birleştirmek.

3 - Bu sadece yeniden bir araya modifiye bölümü ve diğer iki bit bağlamak, kolay bir parçasıdır.

Bu yüzden sadece beni görmezden eğer, karmaşık bu zihin üzerinde korkunç olabilir.

Com zaten bunu yazılı olmadıkça , regex gitmek için en iyi yol olacaktır:

$cleaned_string = preg_replace('/\<.\>/', $raw_text, "");

Ya da böyle bir şey. I / testi regex araştırma gerekir.

Sonra sadece değiştirmek istediğiniz metni bulmak için basit bir $foobar = str_replace($find, $replace_with, $cleaned_string); kullanabilirsiniz.

O Bunun için tüm regex, ve şu anda bildiğim daha Lütfen HTML koymak istediğini fark etmedi.

Ben biliyorum ne olduğunu bilerek, teknik-bilge Herhalde boşluk between kelimeleri göz ardı etmemiş bir ifade kullanmak, ama diye yaptım < ve > arasında parantez, sonra çıktı regex değişken içeren yeteneklerini kullanırlar.

İlginç bir sorun.

Ben bu metin içeren yakın düğümleri bulmak için DOM ve XPath kullanın ve sonra dize bit ne düğüm içinde olduğunu öğrenmek için alt dize eşleştirme kullanmak istiyorsunuz. O da, karakter başına bir karakter eşleştirme ve olası geriye gidilmiştir içerecektir.

İşte konteyner düğümleri bulma, ilk parçasıdır:

<?php
error_reporting(E_ALL);
header('Content-Type: text/plain; charset=UTF-8');

$doc = new DOMDocument();
$doc->loadHTML(<<<EOD
<p>
    <span>
        <i>
            I am <b>Sadi, novice</b> programmer.
        </i>
    </span>
</p>
<ul>
    <li>
        <div>
            I am <em>Cornholio, novice</em> programmer of television shows.
        </div>
    </li>
</ul>
EOD
);
$xpath = new DOMXPath($doc);
// First, get a list of all nodes containing the text anywhere in their tree.
$nodeList = $xpath->evaluate('//*[contains(string(.), "programmer")]');
$deepestNodes = array();
// Now only keep the deepest nodes, because the XPath query will also return HTML, BODY, ...
foreach ($nodeList as $node) {
    $deepestNodes[] = $node;
    $ancestor = $node;
    while (($ancestor = $ancestor->parentNode) && ($ancestor instanceof DOMElement)) {
        $deepestNodes = array_filter($deepestNodes, function ($existingNode) use ($ancestor) {
            return ($ancestor !== $existingNode);
        });
    }
}
foreach ($deepestNodes as $node) {
    var_dump($node->tagName);
}

Ben bu boyunca size yardımcı olur umarım.

Eğer bu kullanmak olacak ne kesin özelliklerini vermediler beri, "Ben sadi, novice programcı değilim" senin örneğini kullanacağız.

$before = 'I am <b>sadi, novice</b> programmer';
$after = preg_replace ('/I am (<.*>)?(.*), novice(<.*>)? programmer/','/I am $1$2,     learner$3 programmer/',$string);

Alternatif olarak, herhangi bir metin için:

$string = '<b>Hello</b>, world!';
$orig = 'Hello';
$replace = 'Goodbye';
$pattern = "/(<.*>)?$orig(<.*>)?/";
$final = "/$1$replace$2/";
$result = preg_replace($pattern,$final,$string);
//$result should now be 'Goodbye, world!'

Yardımcı umuyoruz. : D

Edit: An example of your example, with the second piece of code: $string = 'I am sadi, novice programmer.';
$orig = 'novice';
$replace = 'learner';
$pattern = "/(<.>)?$orig(<.>)?/";
$final = "$1$replace$2";
$result = htmlspecialchars(preg_replace($pattern,$final,$string));
echo $result;

Eğer uzun bir sözcük daha oldu bir şey ararken, eğer tek sorundur.

Düzenleme 2: Son olarak birden fazla kelime üzerinde bunu yapmak için bir yol ile geldi. İşte kod:

function htmlreplace($string,$orig,$replace) 
 {
  $orig = explode(' ',$orig);
  $replace = explode(' ',$replace);
  $result = $string;
  while (count($orig)>0)
   {
    $shift = array_shift($orig);
    $rshift = array_shift($replace);

    $pattern = "/$shift\s?(<.*>)?/";
    $replacement = "$rshift$1";
    $result = preg_replace($pattern,$replacement,$result);
   }
  $result .= implode(' ',$replace);
  return $result;
 }

Eğlenin! : D