Saya ingin versi str_replace()
yang hanya menggantikan kemunculan pertama $search
di $subject
. Apakah ada solusi mudah untuk ini, atau saya perlu solusi hacky?
Saya ingin versi str_replace()
yang hanya menggantikan kemunculan pertama $search
di $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_quote
parameter 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 strrpos
sebagai ganti strpos
.
substr_replace
fungsi 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] => 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%
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] => 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()
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
===false
daripada 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 i
setelah pembatas pola akhir. Perlu dukungan unicode / multibyte? Tambahkan u
setelah pembatas pola akhir. Perlu dukungan batas kata? Tambahkan \b
di 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_replace
lebih cepat.
$string = 'this is my world, not my world';
$find = 'world';
$replace = 'farm';
$result = preg_replace("/$find/",$replace,$string,1);
echo $result;
preg_quote
dari $find
sebelum 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
, $replace
dan / 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_WARNING
seluruh, 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 $subject
daripada false
/ null
atau 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.
$pos
untuk 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 $limit
parameter 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_pos
melebihi panjang. Bukti Kegagalan: 3v4l.org/qGuVIR ... Fungsi Anda dapat menggabungkan return $haystack
kondisi 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()
.
else
statment 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 rev
panggilan 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
string
menggunakan 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 $limit
dan 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 .