Saya ingin versi str_replace()yang hanya menggantikan kemunculan pertama $searchdi $subject. Apakah ada solusi mudah untuk ini, atau saya perlu solusi hacky?
Saya ingin versi str_replace()yang hanya menggantikan kemunculan pertama $searchdi $subject. Apakah ada solusi mudah untuk ini, atau saya perlu solusi hacky?
Jawaban:
Dapat dilakukan dengan preg_replace :
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'
Keajaiban ada di parameter opsional keempat [Batas]. Dari dokumentasi:
[Batas] - Penggantian maksimum yang mungkin untuk setiap pola dalam setiap string subjek. Default ke -1 (tanpa batas).
Padahal, lihat jawaban zombat untuk metode yang lebih efisien (kira-kira, 3-4x lebih cepat).
preg_quote? Sebagai contoh, @ThomasRedstone khawatir pembatas /bisa berbahaya jika muncul $from, tetapi untungnya tidak: itu benar lolos karena preg_quoteparameter kedua (orang dapat dengan mudah mengujinya). Saya tertarik untuk mendengar tentang masalah khusus (yang akan menjadi bug keamanan PCRE serius dalam buku saya).
Tidak ada versi itu, tetapi solusinya sama sekali tidak rusak.
$pos = strpos($haystack, $needle);
if ($pos !== false) {
$newstring = substr_replace($haystack, $replace, $pos, strlen($needle));
}
Cukup mudah, dan menyimpan penalti performa dari ekspresi reguler.
Bonus: Jika Anda ingin mengganti kejadian terakhir , cukup gunakan strrpossebagai ganti strpos.
substr_replacefungsi yang agak sulit untuk digunakan karena semua parameter, masalah sebenarnya adalah bahwa melakukan manipulasi string oleh angka kadang-kadang sulit - Anda harus berhati-hati untuk mengirimkan variabel yang tepat / mengimbangi ke fungsi. Saya benar-benar mengatakan bahwa kode di atas adalah pendekatan yang paling mudah, dan bagi saya, logis.
Sunting: kedua jawaban telah diperbarui dan sekarang benar. Saya akan meninggalkan jawabannya karena timing fungsi masih berguna.
Sayangnya jawaban 'zombat' dan 'terlalu banyak php' tidak benar. Ini adalah revisi dari jawaban yang diposting zombat (karena saya tidak memiliki reputasi yang cukup untuk mengirim komentar):
$pos = strpos($haystack,$needle);
if ($pos !== false) {
$newstring = substr_replace($haystack,$replace,$pos,strlen($needle));
}
Perhatikan strlen ($ jarum), bukan strlen ($ ganti). Contoh Zombat hanya akan bekerja dengan benar jika jarum dan penggantian memiliki panjang yang sama.
Berikut fungsi yang sama dalam suatu fungsi dengan tanda tangan yang sama dengan str_replace milik PHP sendiri:
function str_replace_first($search, $replace, $subject) {
$pos = strpos($subject, $search);
if ($pos !== false) {
return substr_replace($subject, $replace, $pos, strlen($search));
}
return $subject;
}
Ini adalah jawaban revisi dari 'terlalu banyak php':
implode($replace, explode($search, $subject, 2));
Catat 2 di bagian akhir daripada 1. Atau dalam format fungsi:
function str_replace_first($search, $replace, $subject) {
return implode($replace, explode($search, $subject, 2));
}
Saya menghitung waktu dua fungsi dan yang pertama dua kali lebih cepat ketika tidak ada kecocokan yang ditemukan. Mereka memiliki kecepatan yang sama ketika kecocokan ditemukan.
stripos()to the rescue :-)
Saya bertanya-tanya mana yang tercepat, jadi saya menguji semuanya.
Di bawah ini Anda akan menemukan:
Semua fungsi diuji dengan pengaturan yang sama:
$string = 'OOO.OOO.OOO.S';
$search = 'OOO';
$replace = 'B';
Fungsi yang hanya menggantikan kemunculan pertama string dalam string:
substr_replace($string, $replace, 0, strlen($search));
[CONTRIBUTED BY] => zombat
[OOO.OOO.OOO.S] => B.OOO.OOO.S
[AVERAGE TIME] => 0.0000062883
[SLOWER BY] => FASTESTreplace_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%Fungsi yang hanya menggantikan yang terakhir terjadinya string dalam string:
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] => FASTESTstrrev(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()menang hasilnya sederhana; karena ini merupakan fungsi internal. Dua fungsi internal yang dilakukan pengguna dan fungsi yang ditentukan pengguna berbeda dalam kinerja, karena fungsi internal berjalan di lapisan bawah. Jadi mengapa tidak preg_match()? Ekspresi reguler hampir lebih lambat daripada setiap fungsi manipulasi string internal, karena negara mereka mencari dalam string beberapa kali.
substr_replace($string, $replace, 0, strlen($search));) tidak hanya menulis yang statis 0. Bagian dari konvolusi solusi non-regex adalah bahwa mereka perlu "menemukan" titik awal sebelum mengetahui di mana harus mengganti.
Sayangnya, saya tidak tahu fungsi PHP yang bisa melakukan ini.
Anda dapat menggulung sendiri dengan mudah seperti ini:
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));untuk nomor ganti kustom
Saya membuat fungsi kecil ini yang menggantikan string pada string (case-sensitive) dengan batas, tanpa perlu Regexp. Ini bekerja dengan baik.
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;
}
Contoh penggunaan:
$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
===falsedaripada is_bool(menjadi lebih eksplisit - saya memberikan jempol ini hanya karena telah menghindari kegilaan RegExp ! ... dan pada saat yang sama itu berfungsi dan membersihkan solusi ...
preg_bukanlah kegilaan tetapi preferensi pribadi. return preg_replace('/'.preg_quote($search, '/').'/', $replace, $content, 1);cukup mudah dibaca untuk orang yang tidak takut regex. Perlu pencarian case-insensitive? Tambahkan isetelah pembatas pola akhir. Perlu dukungan unicode / multibyte? Tambahkan usetelah pembatas pola akhir. Perlu dukungan batas kata? Tambahkan \bdi kedua sisi string pencarian Anda. Jika Anda tidak ingin regex, jangan gunakan regex. Kuda untuk kursus, tetapi tentu saja bukan kegilaan.
Cara termudah adalah dengan menggunakan ekspresi reguler.
Cara lain adalah menemukan posisi string dengan strpos () dan kemudian substr_replace ()
Tetapi saya benar-benar akan pergi untuk RegExp.
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));
}
=> KODE DIREVISI, jadi anggap beberapa komentar terlalu lama
Dan terima kasih semuanya telah membantu saya meningkatkannya
BUG apa pun, tolong komunikasikan saya; Saya akan memperbaikinya setelah
Jadi, mari kita pergi untuk:
Mengganti 'o' menjadi 'ea' pertama misalnya:
$s='I love you';
$s=str_replace_first('o','ea',$s);
echo $s;
//output: I leave you
Fungsi:
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)), bukan substr($where,$b+1). Dan saya kira itu substr_replacelebih cepat.
$string = 'this is my world, not my world';
$find = 'world';
$replace = 'farm';
$result = preg_replace("/$find/",$replace,$string,1);
echo $result;
preg_quotedari $findsebelum menggunakannya sebagai ekspresi.
preg_quote(). Jawaban duplikat yang terlambat ini dapat dihapus dengan aman dari halaman karena sarannya disediakan oleh yang sebelumnya, dan jawaban yang diterima lebih tinggi dan
Untuk memperluas jawaban @ renocor , saya telah menulis sebuah fungsi yang 100% kompatibel dengan mundur str_replace(). Artinya, Anda dapat mengganti semua kejadian dari str_replace()dengan str_replace_limit()tanpa mengacaukan apa-apa, bahkan mereka menggunakan array untuk $search, $replacedan / atau $subject.
Fungsi bisa sepenuhnya mandiri, jika Anda ingin mengganti panggilan fungsi dengan ($string===strval(intval(strval($string)))), tapi saya sarankan menentangnya karena valid_integer()ini adalah fungsi yang agak berguna ketika berhadapan dengan bilangan bulat yang disediakan sebagai string.
Catatan: Kapan pun memungkinkan, str_replace_limit()akan digunakan str_replace()sebagai gantinya, sehingga semua panggilan ke str_replace()dapat diganti dengan str_replace_limit()tanpa mengkhawatirkan hit ke kinerja.
<?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 penggantian - bbcbbc
$limit = 1; // Limit of 1
$new_string = str_replace_limit($search, $replace, $subject, $count, $limit);
echo $count.' replacements -- '.$new_string;
1 penggantian - bbcabc
$limit = 10; // Limit of 10
$new_string = str_replace_limit($search, $replace, $subject, $count, $limit);
echo $count.' replacements -- '.$new_string;
2 penggantian - 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_WARNINGseluruh, yang merupakan peringatan , bukan sebuah kesalahan . Backtrace sangat berguna untuk mengetahui kode apa yang meneruskan data yang tidak valid ke fungsi di tempat pertama (yang mutlak diperlukan untuk melacak bug dalam produksi). Sedangkan untuk kembali $subjectdaripada false/ nullatau melempar kesalahan, itu hanyalah pilihan pribadi untuk kasus penggunaan saya. Untuk mencocokkan str_replace()fungsionalitas, menggunakan kesalahan fatal yang bisa ditangkap akan menjadi taruhan terbaik (seperti str_replace()halnya ketika memberikan penutupan untuk dua argumen pertama).
preg_replace(). Selanjutnya, preg_replace()/ regex menawarkan penanganan batas kata (jika diinginkan) - sesuatu yang fungsi non-regex tidak akan berikan secara elegan.
Menurut hasil pengujian saya, saya ingin memilih yang biasa_express yang disediakan oleh karim79. (Saya tidak punya cukup reputasi untuk memilihnya sekarang!)
Solusi dari zombat menggunakan terlalu banyak pemanggilan fungsi, saya bahkan menyederhanakan kodenya. Saya menggunakan PHP 5.4 untuk menjalankan kedua solusi sebanyak 100.000 kali, dan inilah hasilnya:
$str = 'Hello abc, have a nice day abc! abc!';
$pos = strpos($str, 'abc');
$str = substr_replace($str, '123', $pos, 3);
==> 1,85 dtk
$str = 'Hello abc, have a nice day abc! abc!';
$str = preg_replace('/abc/', '123', $str, 1);
==> 1,35 detik
Seperti yang Anda lihat. Performa preg_replace tidak seburuk yang dipikirkan banyak orang. Jadi saya akan menyarankan solusi berkelas jika express reguler Anda tidak rumit.
$posuntuk false, sehingga ketika jarum tidak ada di tumpukan jerami, hal itu akan merusak output.
Untuk memperluas jawaban zombat (yang saya yakini sebagai jawaban terbaik), saya membuat versi rekursif dari fungsinya yang mengambil $limitparameter untuk menentukan berapa banyak kejadian yang ingin Anda ganti.
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, jadi jika itu berada di luar panjang string, fungsi ini akan menghasilkan: Warning: strpos(): Offset not contained in string.... Fungsi ini gagal melakukan penggantian bila $start_posmelebihi panjang. Bukti Kegagalan: 3v4l.org/qGuVIR ... Fungsi Anda dapat menggabungkan return $haystackkondisi dan menghindari mendeklarasikan variabel sekali pakai seperti ini: 3v4l.org/Kdmqp Namun, seperti yang saya katakan di komentar di bagian lain halaman ini, saya lebih suka gunakan panggilan yang sangat bersih, langsung, non-rekursif preg_replace().
elsestatment baris ini$start_pos > strlen($haystack) ? $start_pos = strlen($haystack) : '';
Untuk sebuah string
$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
Untuk satu karakter
$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 tersebut merusak string input ketika nilai pencarian tidak ada. Bukti kegagalan: 3v4l.org/HmEml (Dan teknik terakhir dengan semua revpanggilan secara serius berbelit-belit / keras di mata.)
Melengkapi apa yang dikatakan orang, ingat bahwa seluruh string adalah array:
$string = "Lorem ipsum lá lá lá";
$string[0] = "B";
echo $string;
"Borem ipsum lá lá lá"
á. Demonstrasi kegagalan
stringmenggunakan string multibytemb_strlen($subject) != strlen($subject)
$str = "/property/details&id=202&test=123#tab-6p";
$position = strpos($str,"&");
echo substr_replace($str,"?",$position,1);
Dengan menggunakan substr_replace kita dapat mengganti kemunculan karakter pertama hanya dalam string. sebagai & diulang beberapa kali tetapi hanya pada posisi pertama kita harus mengganti & dengan?
Fungsi ini sangat terinspirasi oleh jawaban oleh @renocor. Itu membuat fungsi multi byte aman.
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;
}
Anda bisa menggunakan ini:
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;
}
Temukan contoh ini dari php.net
Pemakaian:
$string = "Thiz iz an examplz";
var_dump(str_replace_once('z','Z', $string));
Keluaran:
ThiZ iz an examplz
Ini mungkin mengurangi kinerja sedikit, tetapi solusi termudah.
strpos()). Diturunkan karena tidak menambah nilai baru ke halaman.
Jika string Anda tidak mengandung karakter multibyte dan jika Anda ingin mengganti hanya satu karakter, Anda dapat menggunakannya strpos
Di sini fungsi yang menangani kesalahan
/**
* 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;
}
Untuk Solusi Loop
<?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;
}
Inilah kelas sederhana yang saya buat untuk membungkus fungsi str_replace () kami yang sedikit dimodifikasi .
Fungsi php :: str_rreplace () kami juga memungkinkan Anda untuk melakukan str_replace () terbalik yang terbatas, yang bisa sangat berguna ketika mencoba mengganti hanya instance X terakhir dari sebuah string.
Contoh-contoh ini menggunakan preg_replace () .
<?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")
Ada satu ruang tambahan lagi tapi itu tidak masalah karena itu untuk skrip backgound dalam kasus saya.
ini jawaban pertama saya di sini, saya berharap bisa melakukannya dengan benar. Mengapa tidak menggunakan argumen keempat fungsi str_replace untuk masalah ini?
mixed str_replace ( mixed $search , mixed $replace , mixed $subject [, int &$count ] )
Hitungan: Jika disahkan, ini akan diatur ke jumlah penggantian yang dilakukan.
sunting: Jawaban ini salah, karena parameter ke-4 dari str_replace adalah variabel yang mendapatkan jumlah penggantian yang dilakukan. Ini tidak konsisten dengan preg_replace , yang memiliki parameter ke-4 $limitdan parameter ke-5&$count .
Sangat mudah untuk menemukan solusi untuk mengganti hanya beberapa contoh pertama atau pertama (dengan memberikan nilai hitungan). Tidak ada banyak solusi untuk mengganti pasangan contoh terakhir atau terakhir.
Mungkin sesuatu seperti str_replace ($ find, $ replace, $ subject, -3) harus menggantikan tiga instance terakhir.
Pokoknya hanya saran saja.
s($subject)->replaceFirst($search)dans($subject)->replaceFirstIgnoreCase($search)membantu, seperti yang ditemukan di perpustakaan mandiri ini .