Ben bir versiyonu istiyorum str_replace()
sadece ilk geçtiği yerini alır $search
içinde $subject
. Bunun kolay bir çözümü var mı, yoksa kötü bir çözüme mi ihtiyacım var?
Ben bir versiyonu istiyorum str_replace()
sadece ilk geçtiği yerini alır $search
içinde $subject
. Bunun kolay bir çözümü var mı, yoksa kötü bir çözüme mi ihtiyacım var?
Yanıtlar:
Preg_replace ile yapılabilir :
function str_replace_first($from, $to, $content)
{
$from = '/'.preg_quote($from, '/').'/';
return preg_replace($from, $to, $content, 1);
}
echo str_replace_first('abc', '123', 'abcdef abcdef abcdef');
// outputs '123def abcdef abcdef'
Sihir isteğe bağlı dördüncü parametrede [Limit]. Belgelerden:
[Limit] - Her bir konu dizesindeki her bir desen için mümkün olan maksimum yedek. Varsayılan değer -1'dir (sınır yoktur).
Gerçi, bkz zombat cevabını daha verimli bir yöntem için (kabaca, 3-4x daha hızlı).
preg_quote
mı? Örneğin, @ThomasRedstone, sınırlayıcının /
göründüğünde tehlikeli olabileceğinden endişe eder $from
, ancak neyse ki öyle değildir: preg_quote
ikinci parametresi nedeniyle düzgün bir şekilde kaçar (biri kolayca test edebilir). Belirli konuları (kitabımda ciddi PCRE güvenlik hataları olurdu) duymak isterim.
Bunun bir sürümü yok, ancak çözüm hiç de aceleci değil.
$pos = strpos($haystack, $needle);
if ($pos !== false) {
$newstring = substr_replace($haystack, $replace, $pos, strlen($needle));
}
Oldukça kolay ve düzenli ifadelerin performans cezasını kaydeder.
Bonus: değiştirmek istiyorsanız son geçtiği, sadece kullanmak strrpos
yerine strpos
.
substr_replace
Tüm parametreler nedeniyle kullanmak için biraz hantal bir işlev olsa da, asıl mesele, sayılarla dize manipülasyonunun bazen zor olması - işlevlere doğru değişkeni / ofseti geçirmeye dikkat etmeniz gerekir. Aslında yukarıdaki kodun en basit ve bana göre mantıklı bir yaklaşım olduğunu söyleyecek kadar ileri giderdim.
Düzenleme: her iki yanıt da güncellendi ve artık doğru. İşlev zamanlamaları hala faydalı olduğundan cevabı bırakacağım.
'Zombat' ve 'çok fazla php' nin cevapları maalesef doğru değil. Bu (bir yorum göndermek için yeterli itibara sahip değilim) yayınlanan cevap zombat bir revizyon olduğunu:
$pos = strpos($haystack,$needle);
if ($pos !== false) {
$newstring = substr_replace($haystack,$replace,$pos,strlen($needle));
}
Strlen ($ replace) yerine steni ($ iğne) not edin. Zombat örneği yalnızca iğne ve değiştirme aynı uzunlukta olduğunda doğru şekilde çalışacaktır.
İşte PHP'nin kendi str_replace işleviyle aynı imzalı bir işlevde aynı işlevsellik:
function str_replace_first($search, $replace, $subject) {
$pos = strpos($subject, $search);
if ($pos !== false) {
return substr_replace($subject, $replace, $pos, strlen($search));
}
return $subject;
}
Bu 'çok fazla php' nin gözden geçirilmiş cevabıdır:
implode($replace, explode($search, $subject, 2));
Sonunda 1 yerine 2 değerini not edin veya işlev biçiminde:
function str_replace_first($search, $replace, $subject) {
return implode($replace, explode($search, $subject, 2));
}
İki işlevi zamanladım ve hiçbir eşleşme bulunmadığında birincisi iki kat daha hızlı. Bir eşleşme bulunduğunda aynı hızdadırlar.
stripos()
to the rescue :-)
Hangisinin en hızlı olduğunu merak ettim, bu yüzden hepsini test ettim.
Aşağıda bulacaksınız:
Tüm işlevler aynı ayarlarla test edilmiştir:
$string = 'OOO.OOO.OOO.S';
$search = 'OOO';
$replace = 'B';
Bir dize içindeki bir dizenin yalnızca ilk oluşumunu değiştiren işlevler :
substr_replace($string, $replace, 0, strlen($search));
[CONTRIBUTED BY] => zombat
[OOO.OOO.OOO.S] => B.OOO.OOO.S
[AVERAGE TIME] => 0.0000062883
[SLOWER BY] => FASTEST
replace_first($search, $replace, $string);
[CONTRIBUTED BY] => too much php
[OOO.OOO.OOO.S] => B.OOO.OOO.S
[AVERAGE TIME] => 0.0000073902
[SLOWER BY] => 17.52%
preg_replace($search, $replace, $string, 1);
[CONTRIBUTED BY] => karim79
[OOO.OOO.OOO.S] => B.OOO.OOO.S
[AVERAGE TIME] => 0.0000077519
[SLOWER BY] => 23.27%
str_replace_once($search, $replace, $string);
[CONTRIBUTED BY] => happyhardik
[OOO.OOO.OOO.S] => B.OOO.OOO.S
[AVERAGE TIME] => 0.0000082286
[SLOWER BY] => 30.86%
str_replace_limit($search, $replace, $string, $count, 1);
[CONTRIBUTED BY] => bfrohs - expanded renocor
[OOO.OOO.OOO.S] => B.OOO.OOO.S
[AVERAGE TIME] => 0.0000083342
[SLOWER BY] => 32.54%
str_replace_limit($search, $replace, $string, 1);
[CONTRIBUTED BY] => renocor
[OOO.OOO.OOO.S] => B.OOO.OOO.S
[AVERAGE TIME] => 0.0000093116
[SLOWER BY] => 48.08%
str_replace_limit($string, $search, $replace, 1, 0);
[CONTRIBUTED BY] => jayoaK
[OOO.OOO.OOO.S] => B.OOO.OOO.S
[AVERAGE TIME] => 0.0000093862
[SLOWER BY] => 49.26%
Bir dize içinde yalnızca bir dizenin son tekrarlamasını değiştiren işlevler :
substr_replace($string, $replace, strrpos($string, $search), strlen($search));
[CONTRIBUTED BY] => oLinkSoftware - modified zombat
[OOO.OOO.OOO.S] => OOO.OOO.B.S
[AVERAGE TIME] => 0.0000068083
[SLOWER BY] => FASTEST
strrev(implode(strrev($replace), explode(strrev($search), strrev($string), 2)));
[CONTRIBUTED BY] => oLinkSoftware
[OOO.OOO.OOO.S] => OOO.OOO.B.S
[AVERAGE TIME] => 0.0000084460
[SLOWER BY] => 24.05%
substr_replace()
kazanmasının nedeni basittir; çünkü bu dahili bir işlevdir. Aynı şeyi yapan iki dahili ve kullanıcı tanımlı işlev performans açısından farklılık gösterir, çünkü dahili işlev alt katmanlarda çalışır. Neden olmasın preg_match()
? Düzenli ifadeler, bir dizede birden çok kez arama yaptıkları için her dahili dize düzenleme işlevinden neredeyse daha yavaştır.
substr_replace($string, $replace, 0, strlen($search));
) üzerindeki kriter sadece statik yazmaz 0
. Normal olmayan çözümlerin evrişiminin bir kısmı, nerede değiştirileceğini bilmeden önce başlangıç noktasını "bulmaları" gerektiğidir.
Ne yazık ki, bunu yapabilen herhangi bir PHP işlevi bilmiyorum.
Kendinizi bu şekilde kolayca yuvarlayabilirsiniz:
function replace_first($find, $replace, $subject) {
// stolen from the comments at PHP.net/str_replace
// Splits $subject into an array of 2 items by $find,
// and then joins the array with $replace
return implode($replace, explode($find, $subject, 2));
}
return implode($replace, explode($find, $subject, $limit+1));
özel numaraları değiştirmek için
Regexp gerek kalmadan, dize (büyük / küçük harf duyarlı) dize sınır ile değiştirir bu küçük işlevi oluşturdu . İyi çalışıyor.
function str_replace_limit($search, $replace, $string, $limit = 1) {
$pos = strpos($string, $search);
if ($pos === false) {
return $string;
}
$searchLen = strlen($search);
for ($i = 0; $i < $limit; $i++) {
$string = substr_replace($string, $replace, $pos, $searchLen);
$pos = strpos($string, $search);
if ($pos === false) {
break;
}
}
return $string;
}
Örnek kullanım:
$search = 'foo';
$replace = 'bar';
$string = 'foo wizard makes foo brew for evil foo and jack';
$limit = 2;
$replaced = str_replace_limit($search, $replace, $string, $limit);
echo $replaced;
// bar wizard makes bar brew for evil foo and jack
===false
tercih is_bool(
etsem de - sadece RegExp deliliğinden kaçındığı için bu başparmakları bırakıyorum ! ... ve aynı zamanda çalışıyor ve temiz bir çözüm ...
preg_
çözümü tercih etmek delilik değil, kişisel bir tercihtir. return preg_replace('/'.preg_quote($search, '/').'/', $replace, $content, 1);
regex'ten korkmayan insanlar için okunması oldukça basittir. Büyük / küçük harfe duyarlı olmayan aramaya mı ihtiyacınız var? i
Son desen sınırlayıcıdan sonra ekleyin . Unicode / multibyte desteğine mi ihtiyacınız var? u
Son desen sınırlayıcıdan sonra ekleyin . Sözcük sınırı desteğine mi ihtiyacınız var? Ekle \b
Arama dizisi her iki tarafında. Normal ifade istemiyorsanız normal ifade kullanmayın. Kurslar için atlar, ama kesinlikle delilik değil.
En kolay yol düzenli ifadeyi kullanmak olacaktır.
Diğer yol, strpos () ve sonra bir substr_replace () ile dizenin konumunu bulmaktır
Ama gerçekten RegExp için gitmek istiyorum.
function str_replace_once($search, $replace, $subject) {
$pos = strpos($subject, $search);
if ($pos === false) {
return $subject;
}
return substr($subject, 0, $pos) . $replace . substr($subject, $pos + strlen($search));
}
=> KOD REVİZE EDİLDİ, bu yüzden bazı yorumları çok eski düşünün
Ve herkese bunu geliştirmeme yardım ettiği için teşekkürler
Herhangi bir hata, lütfen bana ulaşın; Bunu hemen tamir edeceğim
Öyleyse, gidelim:
İlk 'o' yerine 'ea' yerine örneğin:
$s='I love you';
$s=str_replace_first('o','ea',$s);
echo $s;
//output: I leave you
İşlev:
function str_replace_first($a,$b,$s)
{
$w=strpos($s,$a);
if($w===false)return $s;
return substr($s,0,$w).$b.substr($s,$w+strlen($a));
}
substr($where,$b+strlen($this))
, değil substr($where,$b+1)
. Ve sanırım bu substr_replace
daha hızlı.
$string = 'this is my world, not my world';
$find = 'world';
$replace = 'farm';
$result = preg_replace("/$find/",$replace,$string,1);
echo $result;
preg_quote
ait $find
bir ifadesi olarak kullanmadan önce.
preg_quote()
Bu geç yinelenen cevap güvenle sayfasından tasfiye edilebilir onun tavsiyesi önceki sağladığı ve daha yüksek upvoted kabul cevap çünkü..
@ Renocor'un cevabını genişletmek için ,% 100 geriye dönük uyumlu bir fonksiyon yazdım str_replace()
. Yani yerine, olan bütün tekrarlarını str_replace()
ile str_replace_limit()
, kullanıcıların hiçbir şey bozmadan hatta kullanarak dizileri $search
, $replace
ve / veya $subject
.
İşlev çağrısını değiştirmek istiyorsanız işlev tamamen bağımsız olabilir($string===strval(intval(strval($string))))
, ancak valid_integer()
dize olarak sağlanan tamsayılarla uğraşırken oldukça kullanışlı bir işlev olduğu için buna karşı öneriyorum .
Not: Mümkün olduğunda, str_replace_limit()
kullanacağı str_replace()
tüm çağrılar için çok yerine str_replace()
değiştirilebilir str_replace_limit()
performans isabet endişesi duymadan.
<?php
$search = 'a';
$replace = 'b';
$subject = 'abcabc';
$limit = -1; // No limit
$new_string = str_replace_limit($search, $replace, $subject, $count, $limit);
echo $count.' replacements -- '.$new_string;
2 değiştirme - bbcbbc
$limit = 1; // Limit of 1
$new_string = str_replace_limit($search, $replace, $subject, $count, $limit);
echo $count.' replacements -- '.$new_string;
1 yedek - bbcabc
$limit = 10; // Limit of 10
$new_string = str_replace_limit($search, $replace, $subject, $count, $limit);
echo $count.' replacements -- '.$new_string;
2 değiştirme - bbcbbc
<?php
/**
* Checks if $string is a valid integer. Integers provided as strings (e.g. '2' vs 2)
* are also supported.
* @param mixed $string
* @return bool Returns boolean TRUE if string is a valid integer, or FALSE if it is not
*/
function valid_integer($string){
// 1. Cast as string (in case integer is provided)
// 1. Convert the string to an integer and back to a string
// 2. Check if identical (note: 'identical', NOT just 'equal')
// Note: TRUE, FALSE, and NULL $string values all return FALSE
$string = strval($string);
return ($string===strval(intval($string)));
}
/**
* Replace $limit occurences of the search string with the replacement string
* @param mixed $search The value being searched for, otherwise known as the needle. An
* array may be used to designate multiple needles.
* @param mixed $replace The replacement value that replaces found search values. An
* array may be used to designate multiple replacements.
* @param mixed $subject The string or array being searched and replaced on, otherwise
* known as the haystack. If subject is an array, then the search and replace is
* performed with every entry of subject, and the return value is an array as well.
* @param string $count If passed, this will be set to the number of replacements
* performed.
* @param int $limit The maximum possible replacements for each pattern in each subject
* string. Defaults to -1 (no limit).
* @return string This function returns a string with the replaced values.
*/
function str_replace_limit(
$search,
$replace,
$subject,
&$count,
$limit = -1
){
// Set some defaults
$count = 0;
// Invalid $limit provided. Throw a warning.
if(!valid_integer($limit)){
$backtrace = debug_backtrace();
trigger_error('Invalid $limit `'.$limit.'` provided to '.__function__.'() in '.
'`'.$backtrace[0]['file'].'` on line '.$backtrace[0]['line'].'. Expecting an '.
'integer', E_USER_WARNING);
return $subject;
}
// Invalid $limit provided. Throw a warning.
if($limit<-1){
$backtrace = debug_backtrace();
trigger_error('Invalid $limit `'.$limit.'` provided to '.__function__.'() in '.
'`'.$backtrace[0]['file'].'` on line '.$backtrace[0]['line'].'. Expecting -1 or '.
'a positive integer', E_USER_WARNING);
return $subject;
}
// No replacements necessary. Throw a notice as this was most likely not the intended
// use. And, if it was (e.g. part of a loop, setting $limit dynamically), it can be
// worked around by simply checking to see if $limit===0, and if it does, skip the
// function call (and set $count to 0, if applicable).
if($limit===0){
$backtrace = debug_backtrace();
trigger_error('Invalid $limit `'.$limit.'` provided to '.__function__.'() in '.
'`'.$backtrace[0]['file'].'` on line '.$backtrace[0]['line'].'. Expecting -1 or '.
'a positive integer', E_USER_NOTICE);
return $subject;
}
// Use str_replace() whenever possible (for performance reasons)
if($limit===-1){
return str_replace($search, $replace, $subject, $count);
}
if(is_array($subject)){
// Loop through $subject values and call this function for each one.
foreach($subject as $key => $this_subject){
// Skip values that are arrays (to match str_replace()).
if(!is_array($this_subject)){
// Call this function again for
$this_function = __FUNCTION__;
$subject[$key] = $this_function(
$search,
$replace,
$this_subject,
$this_count,
$limit
);
// Adjust $count
$count += $this_count;
// Adjust $limit, if not -1
if($limit!=-1){
$limit -= $this_count;
}
// Reached $limit, return $subject
if($limit===0){
return $subject;
}
}
}
return $subject;
} elseif(is_array($search)){
// Only treat $replace as an array if $search is also an array (to match str_replace())
// Clear keys of $search (to match str_replace()).
$search = array_values($search);
// Clear keys of $replace, if applicable (to match str_replace()).
if(is_array($replace)){
$replace = array_values($replace);
}
// Loop through $search array.
foreach($search as $key => $this_search){
// Don't support multi-dimensional arrays (to match str_replace()).
$this_search = strval($this_search);
// If $replace is an array, use the value of $replace[$key] as the replacement. If
// $replace[$key] doesn't exist, just an empty string (to match str_replace()).
if(is_array($replace)){
if(array_key_exists($key, $replace)){
$this_replace = strval($replace[$key]);
} else {
$this_replace = '';
}
} else {
$this_replace = strval($replace);
}
// Call this function again for
$this_function = __FUNCTION__;
$subject = $this_function(
$this_search,
$this_replace,
$subject,
$this_count,
$limit
);
// Adjust $count
$count += $this_count;
// Adjust $limit, if not -1
if($limit!=-1){
$limit -= $this_count;
}
// Reached $limit, return $subject
if($limit===0){
return $subject;
}
}
return $subject;
} else {
$search = strval($search);
$replace = strval($replace);
// Get position of first $search
$pos = strpos($subject, $search);
// Return $subject if $search cannot be found
if($pos===false){
return $subject;
}
// Get length of $search, to make proper replacement later on
$search_len = strlen($search);
// Loop until $search can no longer be found, or $limit is reached
for($i=0;(($i<$limit)||($limit===-1));$i++){
// Replace
$subject = substr_replace($subject, $replace, $pos, $search_len);
// Increase $count
$count++;
// Get location of next $search
$pos = strpos($subject, $search);
// Break out of loop if $needle
if($pos===false){
break;
}
}
// Return new $subject
return $subject;
}
}
E_USER_WARNING
bir olduğunu boyunca, uyarı , değil bir hata . Geri izleme, hangi verilerin geçersiz veriyi işleve ilk etapta geçirdiğini bulmak için son derece yararlıdır (üretimdeki hataları izlemek için kesinlikle gereklidir). / / Bir hata atmak $subject
yerine geri dönmeye gelince , bu benim kullanım durumum için kişisel bir seçim oldu. İşlevselliği eşleştirmek için , catchable ölümcül hatalarını kullanmak en iyi seçenektir ( ilk iki argüman için bir kapatma sağlarken olduğu gibi ). false
null
str_replace()
str_replace()
preg_replace()
. Ayrıca, preg_replace()
/ regex sözcük sınır işleme (istenirse) sunar - normal olmayan işlevlerin zarif bir şekilde sağlamayacağı bir şey.
Test sonucuma göre, karim79 tarafından sağlanan normal_ifade'ye oy vermek istiyorum. (Şimdi oy kullanmak için yeterli itibarım yok!)
Zombat'ın çözümü çok fazla işlev çağrısı kullanıyor, hatta kodları basitleştiriyorum. Her iki çözümü de 100.000 kez çalıştırmak için PHP 5.4 kullanıyorum ve işte sonuç:
$str = 'Hello abc, have a nice day abc! abc!';
$pos = strpos($str, 'abc');
$str = substr_replace($str, '123', $pos, 3);
==> 1,85 saniye
$str = 'Hello abc, have a nice day abc! abc!';
$str = preg_replace('/abc/', '123', $str, 1);
==> 1,35 sn
Gördüğün gibi. Preg_replace'ın performansı birçok insanın düşündüğü kadar kötü değil. Bu yüzden düzenli ifadeniz karmaşık değilse şık bir çözüm öneririm.
$pos
için false
, bu nedenle iğne samanlıkta yok, bunun çıkışını zarar verir.
Zombat'ın cevabını genişletmek için (ki en iyi cevap olduğuna inanıyorum), işlevinin yinelemeli bir sürümünü, $limit
kaç kez tekrarlamak istediğinizi belirtmek için bir parametre alır .
function str_replace_limit($haystack, $needle, $replace, $limit, $start_pos = 0) {
if ($limit <= 0) {
return $haystack;
} else {
$pos = strpos($haystack,$needle,$start_pos);
if ($pos !== false) {
$newstring = substr_replace($haystack, $replace, $pos, strlen($needle));
return str_replace_limit($newstring, $needle, $replace, $limit-1, $pos+strlen($replace));
} else {
return $haystack;
}
}
}
$start_pos
o dize uzunluğu ötesinde eğer öyleyse, bu fonksiyon oluşturur: Warning: strpos(): Offset not contained in string...
. Bu işlev $start_pos
, uzunluğun ötesinde bir yedek yapamaz . Hata Kanıtı: 3v4l.org/qGuVIR ... Fonksiyonunuz return $haystack
koşulları birleştirebilir ve bu tür tek kullanımlık değişkenleri beyan etmekten kaçınabilir: 3v4l.org/Kdmqp Ancak, bu sayfanın başka yerlerindeki yorumlarda söylediğim gibi, çok temiz, doğrudan, özyinelemesiz bir preg_replace()
çağrı kullanın.
else
statment$start_pos > strlen($haystack) ? $start_pos = strlen($haystack) : '';
Bir dize için
$string = 'OOO.OOO.OOO.S';
$search = 'OOO';
$replace = 'B';
//replace ONLY FIRST occurance of "OOO" with "B"
$string = substr_replace($string,$replace,0,strlen($search));
//$string => B.OOO.OOO.S
//replace ONLY LAST occurance of "OOOO" with "B"
$string = substr_replace($string,$replace,strrpos($string,$search),strlen($search))
//$string => OOO.OOO.B.S
//replace ONLY LAST occurance of "OOOO" with "B"
$string = strrev(implode(strrev($replace),explode(strrev($search),strrev($string),2)))
//$string => OOO.OOO.B.S
Tek bir karakter için
$string[strpos($string,$search)] = $replace;
//EXAMPLE
$string = 'O.O.O.O.S';
$search = 'O';
$replace = 'B';
//replace ONLY FIRST occurance of "O" with "B"
$string[strpos($string,$search)] = $replace;
//$string => B.O.O.O.S
//replace ONLY LAST occurance of "O" with "B"
$string[strrpos($string,$search)] = $replace;
// $string => B.O.O.B.S
substr_replace()
teknik de arama değeri mevcut olmadığında giriş dizesine zarar verir. Başarısızlık kanıtı: 3v4l.org/HmEml (Ve tüm rev
çağrılarla son teknik ciddi şekilde kıvrık / göze sert geliyor.)
İnsanların söylediklerini tamamlayan dizenin tamamının bir dizi olduğunu unutmayın:
$string = "Lorem ipsum lá lá lá";
$string[0] = "B";
echo $string;
"Borem ipsum lá lá lá"
á
. Başarısızlık gösteri
string
Kullanarak çok baytlı bir dize olup olmadığını doğrulayabilirsinizmb_strlen($subject) != strlen($subject)
$str = "/property/details&id=202&test=123#tab-6p";
$position = strpos($str,"&");
echo substr_replace($str,"?",$position,1);
Substr_replace kullanarak ilk karakterin oluşumunu yalnızca dizede değiştirebiliriz. olarak & birden çok kez tekrarlanır, ancak sadece ilk konumda & yerine?
Bu işlev, @renocor'un cevabından büyük ölçüde ilham alıyor. Fonksiyonu çok baytlı güvenli hale getirir.
function str_replace_limit($search, $replace, $string, $limit)
{
$i = 0;
$searchLength = mb_strlen($search);
while(($pos = mb_strpos($string, $search)) !== false && $i < $limit)
{
$string = mb_substr_replace($string, $replace, $pos, $searchLength);
$i += 1;
}
return $string;
}
function mb_substr_replace($string, $replacement, $start, $length = null, $encoding = null)
{
$string = (array)$string;
$encoding = is_null($encoding) ? mb_internal_encoding() : $encoding;
$length = is_null($length) ? mb_strlen($string) - $start : $length;
$string = array_map(function($str) use ($replacement, $start, $length, $encoding){
$begin = mb_substr($str, 0, $start, $encoding);
$end = mb_substr($str, ($start + $length), mb_strlen($str), $encoding);
return $begin . $replacement . $end;
}, $string);
return ( count($string) === 1 ) ? $string[0] : $string;
}
Bunu kullanabilirsiniz:
function str_replace_once($str_pattern, $str_replacement, $string){
if (strpos($string, $str_pattern) !== false){
$occurrence = strpos($string, $str_pattern);
return substr_replace($string, $str_replacement, strpos($string, $str_pattern), strlen($str_pattern));
}
return $string;
}
Bu örneği php.net adresinden buldum
Kullanımı:
$string = "Thiz iz an examplz";
var_dump(str_replace_once('z','Z', $string));
Çıktı:
ThiZ iz an examplz
Bu, performansı biraz azaltabilir, ancak en kolay çözümdür.
strpos()
) zaten sunuldu . Sayfaya yeni bir değer katmadığı için indirildi.
Dizeniz herhangi bir çok baytlı karakter içermiyorsa ve yalnızca bir karakter değiştirmek istiyorsanız, strpos
İşte hataları işleyen bir işlev
/**
* Replace the first occurence of given string
*
* @param string $search a char to search in `$subject`
* @param string $replace a char to replace in `$subject`
* @param string $subject
* @return string
*
* @throws InvalidArgumentException if `$search` or `$replace` are invalid or if `$subject` is a multibytes string
*/
function str_replace_first(string $search , string $replace , string $subject) : string {
// check params
if(strlen($replace) != 1 || strlen($search) != 1) {
throw new InvalidArgumentException('$search & $replace must be char');
}elseif(mb_strlen($subject) != strlen($subject)){
throw new InvalidArgumentException('$subject is an multibytes string');
}
// search
$pos = strpos($subject, $search);
if($pos === false) {
// not found
return $subject;
}
// replace
$subject[$replace] = $subject;
return $subject;
}
Döngü Çözümü için
<?php
echo replaceFirstMatchedChar("&", "?", "/property/details&id=202&test=123#tab-6");
function replaceFirstMatchedChar($searchChar, $replaceChar, $str)
{
for ($i = 0; $i < strlen($str); $i++) {
if ($str[$i] == $searchChar) {
$str[$i] = $replaceChar;
break;
}
}
return $str;
}
İşte biraz değiştirilmiş str_replace () ' ı sarmak için oluşturduğum basit bir sınıf fonksiyonlarımızı .
Bizim php :: str_rreplace () fonksiyonumuz, bir dizenin yalnızca son X örneğini değiştirmeye çalışırken çok kullanışlı olabilecek bir ters, sınırlı str_replace () gerçekleştirmenize de izin verir.
Bu örneklerin her ikisi de preg_replace () yöntemini kullanır .
<?php
class php {
/**
* str_replace() from the end of a string that can also be limited e.g. replace only the last instance of '</div>' with ''
*
* @param string $find
* @param string $replace
* @param string $subject
* @param int $replacement_limit | -1 to replace all references
*
* @return string
*/
public static function str_replace($find, $replace, $subject, $replacement_limit = -1) {
$find_pattern = str_replace('/', '\/', $find);
return preg_replace('/' . $find_pattern . '/', $replace, $subject, $replacement_limit);
}
/**
* str_replace() from the end of a string that can also be limited e.g. replace only the last instance of '</div>' with ''
*
* @param string $find
* @param string $replace
* @param string $subject
* @param int $replacement_limit | -1 to replace all references
*
* @return string
*/
public static function str_rreplace($find, $replace, $subject, $replacement_limit = -1) {
return strrev( self::str_replace(strrev($find), strrev($replace), strrev($subject), $replacement_limit) );
}
}
$str = "Hello there folks!"
$str_ex = explode("there, $str, 2); //explodes $string just twice
//outputs: array ("Hello ", " folks")
$str_final = implode("", $str_ex); // glues above array together
// outputs: str("Hello folks")
Bir ek alan daha var ama benim durumumda artalan komut dosyası için olduğu gibi önemli değildi.
bu benim ilk cevabım, umarım doğru yapmayı umarım. Neden bu sorun için str_replace işlevinin dördüncü bağımsız değişkenini kullanmıyorsunuz?
mixed str_replace ( mixed $search , mixed $replace , mixed $subject [, int &$count ] )
count: Geçilirse, gerçekleştirilen değiştirme sayısına ayarlanır.
edit: Bu cevap yanlış, çünkü str_replace 4 parametresi yapılan değiştirme sayısı atanan bir değişkendir. Bu, 4. parametreye ve 5. parametreye sahip preg_replace ile tutarsız .$limit
&$count
Yalnızca ilk veya ilk birkaç örneği değiştirmek için bir çözüm bulmak kolaydır (sayı değerini vererek). Örneğin son veya son çiftini değiştirmek için çok fazla çözüm yoktur.
Belki str_replace ($ find, $ replace, $ Subject, -3) gibi bir şey son üç örneğin yerine geçmelidir.
Her neyse, sadece bir öneri.
s($subject)->replaceFirst($search)
ve bulabileceğinizs($subject)->replaceFirstIgnoreCase($search)
faydalı olabilir .