Wildcard PHP yerine

4 Cevap php

PHP düzenli ifadeler kullanarak hiçbir deneyimi var, bu yüzden genellikle str_replace dizi (), substr (), strpos (), strstr () vb (siz anladınız) kullanarak bazı kıvrık fonksiyon yazmak.

Ben bu doğru yapmak istiyorum bu sefer, ben bunun için bir regex kullanmak gerekiyor biliyorum, ama (Ereg veya gebelik) kullanmak için ne kadar karıştı, ve sözdizimi tam olarak nasıl olmalıdır.

NOTE: I am NOT parsing HTML, or XML, and sometimes I will be using delimiters other than (for example, | or ~ or [tag] or ::). I am looking for a generic way to do a wildcard replace in between two known delimiters using regex, I am not building an HTML or XML parser.

Ne gerek bu yerini bir regex olduğunu:

<sometag>everything in here</sometag>

Bu ile:

<sometag>new contents</sometag>

Ben biraz çevrimiçi belgelerine okudum, ama kafam karıştı, ve regex uzmanlar basit bir çözüm patlatabilir içinizden birini umuyorum. Ben, bir işleve böyle bir şey değerlerini geçecek şüpheli:

$new_text = swapText ( "<sometag>", $the_new_text_to_go_into_the_dag );

function swapText ( $in_tag_with_brackets_to_update, $in_new_text ) {
 // define tags
 $starting_tag  = $in_tag_with_brackets_to_update;
 $ending_tag    = str_replace( "<", "</", $in_tag_with_brackets_to_update) );

 // not sure if this is the proper regex match string or not
 // and/or if any escaping needs to be done on the tags
 $find_string         = "{$starting_tag}.*{$ending_tag}";
 $replace_with_string = "{$starting_tag}{$in_new_text}{$ending_tag}";

 // after some regex, this function should return new version of <tag>data</tag>
}

Teşekkürler.

4 Cevap

@ OP, görev çok basit ise karmaşık regex ya da bir ayrıştırıcı kullanmak gerek yoktur. Bir örnek sadece normal alt dizeleri kullanarak ....

$mystr='<sometag>everything in here</sometag>';
$start=strpos($mystr,"<sometag>");
$end=strpos($mystr,"</sometag>");
print substr($mystr,0,$start+strlen("<sometag>") ) . "new value" . substr($mystr,$end);

Eğer xml ayrıştırmak için gidiyor ve daha sonra bir xml örnek göstermek için gider olmadığını söylüyorlar. Bu biraz kafa karıştırıcı.

Şimdi, xml ayrıştırmak için normal ifadeler kullanamazsınız nedeni, onlar içeriksel değil olmasıdır. Bu nedenle düzenli ifadeler için kullanılamaz ki sorunların bir bütün sınıf vardır. Bu (onlar xml olsun veya olmasın), iç içe geçmiş etiketleri içerir, bu nedenle aklınızda tutun.

Bu yoldan, kullanıyor olmalıdır preg - değil ereg. ereg normal ifadelerin daha az kullanılan yavaş artık önerilmemektedir türüdür. Unut gitsin.

PCRE'nin kullandığı gebelik dil, bir . (nokta) olduğu (Perl uyumlu düzenli ifadeleri), In (yeni satır hariç) herhangi bir tek karakterle eşleşir bir joker vardır. Bir maçtan sonra bir nicelik koyabilirsiniz. Bir nicelik gibi {1,3} (en azından bir anlam, ama yukarı 3) ya da böyle + olarak, kısa el sembollerinden biri olarak kullanabilirsiniz numaraları açık bir dizi olabilir ya da * (sıfır dahil olmak üzere herhangi bir sayıda Anlamı) (en az birini, yani {1,} Kısa). Bu bilgi ile, .* ile bir şey eşleşebilir.

Varsayılan olarak, ifadeler (açgözlü olarak bilinen) olası en büyük desen maç olacak. Sen ? değiştirici ile değiştirebilirsiniz. Böylece .*? şey maç, ama mümkün olan en kısa desen alacaktır. Bu daha sonra aşağıdaki gibi herhangi ayrılmış değer maç için kullanılabilir:

~<foo>.*?</foo>~

Ben ifadesinde / kaçmak zorunda kalmamak için burada sınırlayıcı olarak ~ kullanıyorum unutmayın. Standart ifadesi bu gibi görünüyordu olurdu bu durumda, sınırlayıcı olarak / kullanmaktır:

/<foo>.*?<\/foo>/

Genel olarak, yukarıda bir nokta daha negatif karakter sınıfını maç, ama sizin için basit şeyleri tutmak için, sizin cilt altında temel almak kadar sadece bu görmezden çok daha iyi, çünkü kötü bir uygulamadır. Çoğu durumda çalışacağız. Içerik bir satır karakteri içeriyorsa, özellikle . eşleşmiyor satırsonlarının yana, bu iş olmaz. Bu ihtiyacınız varsa iki şeyden birini yapabilirsiniz: Eğer satırsonu içeren, bir karakter sınıfı ile . değiştirin ifade için bir modifier ekleyebilir veya Ya. Örneğin [\s\S] (bir boşluk karakteri şey aynıdır or, bir boşluk olmayan karakter, Anlamı). Bu ifade daha sonra nasıl görüneceğini olduğunu:

~<foo>.*?</foo>~s

Veya:

~<foo>[\s\S]*?</foo>~

Çalışma tüm bu koymak için, en preg_replace onu işleve geçmesine izin:

echo preg_replace('~<foo>.*?</foo>~s', '<foo>Lorem Ipsum</foo>', $input);

Senin etiket isimleri değişken iseniz, size bir SQL sorgusu ile yaptığınız gibi ifade kurabilirsiniz. Sadece SQL gibi, bazı karakterler kaçmak gerekir. preg_quote Bunun için kullanın:

function swapText($tagname, $replacement_text, $input) {
  $tagname_escaped = preg_quote($tagname, '~');
  return preg_replace(
    '~<' . $tagname_escaped . '>.*?</' . $tagname_escaped . '>~s',
    '<' . $tagname . '>' . $replacement_text . '</' . $tagname . '>',
    $input);
}

Eğer değiştiriyorsanız html ise Birincisi, simple html dom gibi bir şey kullanabilirsiniz. Biçimi demek tam olarak ne ise (gibi, <sometag> olamaz <sometag >), daha sonra regex kullanmak için Tamam olabilir.

Onlar artık yok gibi, preg işlevlerini kullanın, ereg dayalı fonksiyonları kullanmak yok.

preg_replace('%(<sometag>)[^<]*(</sometag>)%i', '$1something else$2', $str);

EDIT
A slightly better version of the above, now supports having a < in the text

preg_replace('%(<sometag>).*?(</sometag>)%i', '$1something else$2', $str);

1 $ ve 2 $ parantez arasındaki Bahisler metin vardır. Bu sabit olduğu gibi, sürekli ile değiştirilebilir

preg_replace('%<sometag>.*?</sometag>%i', '<sometag>something else</sometag>', $str);

Ben joker bir dizenin parçalarını değiştirmek için aşağıdaki işlevi yazdık:

function wildcardReplace($String,$Search,$Filler,$Wildcard = '???'){

        list($startStr,$endStr) = explode($Wildcard,$Search);

        $start = strpos($String,$startStr);

        // Make sure the end point is the first closest match after the start string.   

        $endofstarter = strpos($String,$startStr) + strlen($startStr);

        $startofender = strpos(
                    substr($String,$endofstarter),
                    $endStr
                ) + $endofstarter;


        $Result = substr($String,0,$start+strlen($startStr) ) . $Filler. substr($String,$startofender);

        // Replace any remaining stuff

        $RemainingString = substr($String,$startofender);

        // If theres any matches left, replace them

        if(strpos($RemainingString,$startStr)>-1) $Result = str_replace($RemainingString,wildcardReplace($RemainingString,$Search,$Filler),$Result);

        return $Result;
}

Örnek kullanım: $Output = wildcardReplace('<a href="http://www.youtube.com/watch?v=dQw4w9WgXcQ"><img src="rickroll.png" width="500"></a>','width="???"',350,'???')