Tôi muốn một phiên bản str_replace()
chỉ thay thế lần xuất hiện đầu tiên $search
trong $subject
. Có một giải pháp dễ dàng cho việc này, hay tôi cần một giải pháp hacky?
Tôi muốn một phiên bản str_replace()
chỉ thay thế lần xuất hiện đầu tiên $search
trong $subject
. Có một giải pháp dễ dàng cho việc này, hay tôi cần một giải pháp hacky?
Câu trả lời:
Có thể được thực hiện với preg numplace :
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'
Phép thuật nằm trong tham số thứ tư tùy chọn [Giới hạn]. Từ tài liệu:
[Giới hạn] - Thay thế tối đa có thể có cho mỗi mẫu trong mỗi chuỗi chủ đề. Mặc định là -1 (không giới hạn).
Mặc dù vậy, hãy xem câu trả lời của zombat để biết phương pháp hiệu quả hơn (nhanh hơn khoảng 3-4 lần).
preg_quote
? Ví dụ: @ThomasRedstone lo lắng rằng dấu phân cách /
có thể nguy hiểm nếu nó xuất hiện $from
, nhưng may mắn thay, đó không phải là: nó được thoát đúng vì preg_quote
tham số thứ hai (người ta có thể dễ dàng kiểm tra điều đó). Tôi rất muốn nghe về các vấn đề cụ thể (đó sẽ là lỗi bảo mật PCRE nghiêm trọng trong cuốn sách của tôi).
Không có phiên bản nào của nó, nhưng giải pháp không hề khó hiểu.
$pos = strpos($haystack, $needle);
if ($pos !== false) {
$newstring = substr_replace($haystack, $replace, $pos, strlen($needle));
}
Khá dễ dàng, và tiết kiệm hình phạt hiệu suất của các biểu thức thông thường.
Tiền thưởng: Nếu bạn muốn thay thế lần xuất hiện cuối cùng , chỉ cần sử dụng strrpos
thay thế strpos
.
substr_replace
là một hàm hơi khó sử dụng do tất cả các tham số, nhưng vấn đề thực sự là việc thực hiện thao tác chuỗi bằng số đôi khi chỉ là khó khăn - bạn phải cẩn thận để chuyển đúng / bù cho các hàm. Tôi thực sự đã đi xa để nói rằng đoạn mã trên là cách tiếp cận đơn giản nhất và theo tôi, hợp lý.
Chỉnh sửa: cả hai câu trả lời đã được cập nhật và bây giờ là chính xác. Tôi sẽ để lại câu trả lời vì thời gian chức năng vẫn còn hữu ích.
Rất tiếc, câu trả lời của 'zombat' và 'quá nhiều php' không đúng. Đây là bản sửa đổi cho câu trả lời zombat đã đăng (vì tôi không đủ uy tín để đăng bình luận):
$pos = strpos($haystack,$needle);
if ($pos !== false) {
$newstring = substr_replace($haystack,$replace,$pos,strlen($needle));
}
Lưu ý strlen ($ kim), thay vì strlen ($ thay thế). Ví dụ của Zombat sẽ chỉ hoạt động chính xác nếu kim và thay thế có cùng độ dài.
Đây là chức năng tương tự trong một chức năng có cùng chữ ký với str numplace của PHP:
function str_replace_first($search, $replace, $subject) {
$pos = strpos($subject, $search);
if ($pos !== false) {
return substr_replace($subject, $replace, $pos, strlen($search));
}
return $subject;
}
Đây là câu trả lời sửa đổi của 'quá nhiều php':
implode($replace, explode($search, $subject, 2));
Lưu ý 2 ở cuối thay vì 1. Hoặc ở định dạng hàm:
function str_replace_first($search, $replace, $subject) {
return implode($replace, explode($search, $subject, 2));
}
Tôi đã tính thời gian cho hai chức năng và chức năng đầu tiên nhanh gấp đôi khi không tìm thấy kết quả khớp. Chúng có cùng tốc độ khi một trận đấu được tìm thấy.
stripos()
để giải cứu :-)
Tôi tự hỏi cái nào là nhanh nhất, vì vậy tôi đã kiểm tra tất cả.
Dưới đây bạn sẽ tìm thấy:
Tất cả các chức năng đã được kiểm tra với cùng một cài đặt:
$string = 'OOO.OOO.OOO.S';
$search = 'OOO';
$replace = 'B';
Các hàm chỉ thay thế lần xuất hiện đầu tiên của chuỗi trong chuỗi:
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%
Các hàm chỉ thay thế lần xuất hiện cuối cùng của chuỗi trong chuỗi:
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()
chiến thắng kết quả là đơn giản; bởi vì nó là một chức năng nội bộ. Hai chức năng bên trong và cùng một thứ do người dùng định nghĩa khác nhau về hiệu năng, bởi vì chức năng bên trong chạy ở các lớp thấp hơn. Vậy tại sao khôngpreg_match()
? Các biểu thức thông thường hầu như chậm hơn mọi hàm thao tác chuỗi bên trong, do quốc gia của chúng tìm kiếm trong một chuỗi nhiều lần.
substr_replace($string, $replace, 0, strlen($search));
) của bạn không chỉ đơn thuần là viết tĩnh đó 0
. Một phần của sự kết hợp của các giải pháp phi regex là chúng cần "tìm" điểm bắt đầu trước khi biết nơi để thay thế.
Thật không may, tôi không biết bất kỳ hàm PHP nào có thể làm điều này.
Bạn có thể tự cuộn khá dễ dàng như thế này:
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));
cho các số thay thế tùy chỉnh
Tôi đã tạo ra hàm nhỏ này thay thế chuỗi trên chuỗi (phân biệt chữ hoa chữ thường) có giới hạn mà không cần Regrec. Nó hoạt động tốt.
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;
}
Ví dụ sử dụng:
$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
thay vì is_bool(
nói rõ ràng hơn - tôi đang giơ ngón tay cái này lên chỉ vì nó đã tránh được sự điên rồ của RegExp ! ... và đồng thời nó đang hoạt động và giải pháp sạch sẽ ...
preg_
giải pháp dễ dàng tùy biến không phải là sự điên rồ mà là một sở thích cá nhân. return preg_replace('/'.preg_quote($search, '/').'/', $replace, $content, 1);
khá đơn giản để đọc cho những người không sợ regex. Cần tìm kiếm không phân biệt chữ hoa chữ thường? Thêm i
sau dấu phân cách mẫu kết thúc. Cần hỗ trợ unicode / multibyte? Thêm u
sau dấu phân cách mẫu kết thúc. Cần hỗ trợ ranh giới từ? Thêm \b
vào cả hai mặt của chuỗi tìm kiếm của bạn. Nếu bạn không muốn regex, đừng sử dụng regex. Ngựa cho các khóa học, nhưng chắc chắn không điên.
Cách dễ nhất sẽ là sử dụng biểu thức chính quy.
Một cách khác là tìm vị trí của chuỗi với strpose () và sau đó là một lớp nền ()
Nhưng tôi thực sự sẽ đi cho 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));
}
=> MÃ ĐƯỢC SỬA ĐỔI, vì vậy hãy xem xét một số ý kiến quá cũ
Và cảm ơn mọi người giúp tôi cải thiện điều đó
Bất kỳ BUG, xin vui lòng liên lạc với tôi; Tôi sẽ sửa nó ngay sau đó
Vì vậy, hãy cho:
Thay thế 'o' đầu tiên thành 'ea' chẳng hạn:
$s='I love you';
$s=str_replace_first('o','ea',$s);
echo $s;
//output: I leave you
Chức năng:
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))
, không substr($where,$b+1)
. Và tôi đoán đó substr_replace
là nhanh hơn.
$string = 'this is my world, not my world';
$find = 'world';
$replace = 'farm';
$result = preg_replace("/$find/",$replace,$string,1);
echo $result;
preg_quote
số $find
trước khi sử dụng nó như là một biểu thức.
preg_quote()
. Câu trả lời trùng lặp muộn này có thể được xóa khỏi trang vì lời khuyên của nó được cung cấp bởi câu trả lời được chấp nhận trước đó và cao hơn được chấp nhận.
Để mở rộng câu trả lời của @ renocor , tôi đã viết một hàm tương thích ngược 100% với str_replace()
. Nghĩa là, bạn có thể thay thế tất cả các lần xuất hiện của str_replace()
có str_replace_limit()
mà không rối tung bất cứ điều gì, ngay cả những người sử dụng mảng cho $search
, $replace
và / hoặc $subject
.
Hàm này có thể hoàn toàn khép kín, nếu bạn muốn thay thế lệnh gọi hàm ($string===strval(intval(strval($string))))
, nhưng tôi khuyên bạn nên chống lại nó vì đây valid_integer()
là một hàm khá hữu ích khi xử lý các số nguyên được cung cấp dưới dạng chuỗi.
Lưu ý: Bất cứ khi nào có thể, str_replace_limit()
sẽ sử dụng str_replace()
thay thế, vì vậy tất cả các cuộc gọi str_replace()
có thể được thay thế str_replace_limit()
mà không phải lo lắng về hiệu suất.
<?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 sự thay thế - bbcbbc
$limit = 1; // Limit of 1
$new_string = str_replace_limit($search, $replace, $subject, $count, $limit);
echo $count.' replacements -- '.$new_string;
1 thay thế - bbcabc
$limit = 10; // Limit of 10
$new_string = str_replace_limit($search, $replace, $subject, $count, $limit);
echo $count.' replacements -- '.$new_string;
2 sự thay thế - 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
xuyên suốt, đó là một cảnh báo , không phải là một lỗi . Backtrace cực kỳ hữu ích để tìm ra mã nào đang truyền dữ liệu không hợp lệ cho hàm ở vị trí đầu tiên (điều này hoàn toàn cần thiết để theo dõi các lỗi trong sản xuất). Đối với việc trả lại $subject
thay vì false
/ null
hoặc ném lỗi, đó đơn giản là một lựa chọn cá nhân cho trường hợp sử dụng của tôi. Để phù hợp với str_replace()
chức năng của nó, sử dụng các lỗi nghiêm trọng có thể bắt được sẽ là cách tốt nhất (cũng như str_replace()
khi cung cấp một bao đóng cho hai đối số đầu tiên).
preg_replace()
. Hơn nữa, preg_replace()
/ regex cung cấp xử lý ranh giới từ (nếu muốn) - thứ mà các hàm không phải regex sẽ không cung cấp một cách thanh lịch.
Theo kết quả thử nghiệm của tôi, tôi muốn bỏ phiếu cho thường xuyên được cung cấp bởi karim79. (Tôi không có đủ danh tiếng để bỏ phiếu ngay bây giờ!)
Giải pháp từ zombat sử dụng quá nhiều lệnh gọi hàm, tôi thậm chí còn đơn giản hóa các mã. Tôi đang sử dụng PHP 5.4 để chạy cả hai giải pháp trong 100.000 lần và đây là kết quả:
$str = 'Hello abc, have a nice day abc! abc!';
$pos = strpos($str, 'abc');
$str = substr_replace($str, '123', $pos, 3);
==> 1,85 giây
$str = 'Hello abc, have a nice day abc! abc!';
$str = preg_replace('/abc/', '123', $str, 1);
==> 1,35 giây
Bạn có thể thấy. Hiệu suất của preg numplace không quá tệ như nhiều người nghĩ. Vì vậy, tôi muốn đề xuất giải pháp đẳng cấp nếu biểu thức thông thường của bạn không phức tạp.
$pos
chofalse
, vì vậy khi kim không tồn tại trong đống cỏ khô, nó sẽ làm hỏng đầu ra.
Để mở rộng câu trả lời của zombat (mà tôi tin là câu trả lời hay nhất), tôi đã tạo một phiên bản đệ quy của hàm anh ta có một $limit
tham số để chỉ định số lần xuất hiện bạn muốn thay thế.
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
, vì vậy nếu vượt quá độ dài chuỗi, chức năng này sẽ tạo ra:Warning: strpos(): Offset not contained in string...
. Chức năng này không thực hiện thay thế khi $start_pos
vượt quá độ dài. Bằng chứng về sự thất bại: 3v4l.org/qGuVIR ... Chức năng của bạn có thể kết hợp các return $haystack
điều kiện và tránh khai báo các biến sử dụng một lần như thế này: 3v4l.org/Kdmqp Tuy nhiên, như tôi đã nói trong các nhận xét ở đâu đó trên trang này, tôi muốn nói sử dụng một preg_replace()
cuộc gọi rất sạch sẽ, trực tiếp, không đệ quy .
else
Statment$start_pos > strlen($haystack) ? $start_pos = strlen($haystack) : '';
Cho một chuỗi
$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
Cho một nhân vật
$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()
kỹ thuật này đều làm hỏng chuỗi đầu vào khi không có giá trị tìm kiếm. Bằng chứng về sự thất bại: 3v4l.org/HmEml (Và kỹ thuật cuối cùng với tất cả các rev
cuộc gọi bị ảnh hưởng nghiêm trọng / khó khăn trên mắt.)
Bổ sung cho những gì mọi người nói, hãy nhớ rằng toàn bộ chuỗi là một mảng:
$string = "Lorem ipsum lá lá lá";
$string[0] = "B";
echo $string;
"Borem ipsum lá lá"
á
. Trình diễn thất bại
string
chuỗi của bạn có phải là chuỗi đa bào hay khôngmb_strlen($subject) != strlen($subject)
$str = "/property/details&id=202&test=123#tab-6p";
$position = strpos($str,"&");
echo substr_replace($str,"?",$position,1);
Sử dụng lớp nền, chúng ta có thể thay thế sự xuất hiện của ký tự đầu tiên chỉ trong chuỗi. như & được lặp lại nhiều lần nhưng chỉ ở vị trí đầu tiên chúng ta phải thay thế & bằng?
Chức năng này được lấy cảm hứng rất nhiều từ câu trả lời của @renocor. Nó làm cho chức năng đa byte an toàn.
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;
}
Bạn có thể sử dụng điều này:
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;
}
Tìm thấy ví dụ này từ php.net
Sử dụng:
$string = "Thiz iz an examplz";
var_dump(str_replace_once('z','Z', $string));
Đầu ra:
ThiZ iz an examplz
Điều này có thể làm giảm hiệu suất một chút, nhưng giải pháp dễ nhất.
strpos()
). Bị bỏ qua vì nó không thêm bất kỳ giá trị mới nào vào trang.
Nếu chuỗi của bạn không chứa bất kỳ ký tự đa dòng nào và nếu bạn muốn thay thế chỉ một ký tự, bạn chỉ cần sử dụng strpos
Đây là một chức năng xử lý lỗi
/**
* 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;
}
Đối với giải pháp vòng lặp
<?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;
}
Đây là một lớp đơn giản mà tôi đã tạo để bao bọc các hàm str numplace () được sửa đổi một chút của chúng tôi .
Hàm php :: str_rreplace () của chúng tôi cũng cho phép bạn thực hiện một str numplace () bị giới hạn, có thể rất tiện lợi khi cố gắng chỉ thay thế (các) thể hiện X cuối cùng của chuỗi.
Cả hai ví dụ này đều sử dụng preg numplace () .
<?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")
Có thêm một không gian nữa nhưng nó không thành vấn đề vì nó là kịch bản backgound trong trường hợp của tôi.
Đây là câu trả lời đầu tiên của tôi ở đây, tôi hy vọng sẽ làm điều đó một cách chính xác. Tại sao không sử dụng đối số thứ tư của hàm str numplace cho vấn đề này?
mixed str_replace ( mixed $search , mixed $replace , mixed $subject [, int &$count ] )
đếm: Nếu được thông qua, điều này sẽ được đặt thành số lần thay thế được thực hiện.
chỉnh sửa: Câu trả lời này là sai, bởi vì tham số thứ 4 của str numplace là một biến được chỉ định số lần thay thế được thực hiện. Điều này không phù hợp với preg numplace , có tham số thứ 4 $limit
và tham số thứ 5 &$count
.
Thật dễ dàng để tìm một giải pháp để chỉ thay thế một vài trường hợp đầu tiên hoặc đầu tiên (bằng cách đưa ra giá trị đếm). Không có nhiều giải pháp để thay thế ví dụ cuối cùng hoặc cuối cùng.
Có lẽ một cái gì đó như str numplace ($ find, $ thay thế, $ topic, -3) sẽ thay thế ba trường hợp cuối cùng.
Dù sao, chỉ là một gợi ý.
s($subject)->replaceFirst($search)
vàs($subject)->replaceFirstIgnoreCase($search)
hữu ích, như được tìm thấy trong thư viện độc lập này .