str_replace를 사용하여 첫 번째 일치 시에만 작동합니까?
의 버전을 원합니다.str_replace()
할 뿐입니다.$search
$subject
이문 대한 한한 운? ?? ???니면면 해답 ?? ????
어떤 버전도 없지만, 해결책은 전혀 해킹되지 않았습니다.
$pos = strpos($haystack, $needle);
if ($pos !== false) {
$newstring = substr_replace($haystack, $replace, $pos, strlen($needle));
}
매우 쉽고 정규 표현의 성능 저하를 방지합니다.
보너스: 마지막 오카렌스를 바꾸려면 다음 명령을 사용하십시오.strrpos
strpos
.
preg_replace를 사용하여 수행할 수 있습니다.
function str_replace_first($search, $replace, $subject)
{
$search = '/'.preg_quote($search, '/').'/';
return preg_replace($search, $replace, $subject, 1);
}
echo str_replace_first('abc', '123', 'abcdef abcdef abcdef');
// outputs '123def abcdef abcdef'
매직은 옵션의 네 번째 파라미터 [Limit]에 있습니다.매뉴얼에서 다음 항목을 참조하십시오.
[제한] - 각 제목 문자열의 각 패턴에 대해 가능한 최대 치환 수.기본값은 -1(제한 없음)입니다.
그러나 보다 효율적인 방법(대략 3~4배 더 빠름)에 대해서는 좀바트의 답변을 참조하십시오.
편집: 두 답변이 모두 업데이트되었으며 현재 정답입니다.아직 기능 타이밍이 유용하기 때문에 답변을 남겨두겠습니다.
좀바트'와 'too much php'의 답변은 안타깝게도 올바르지 않습니다.이것은 좀바에 투고된 답변의 수정입니다(댓글을 달 만한 평판이 없기 때문에).
$pos = strpos($haystack,$needle);
if ($pos !== false) {
$newstring = substr_replace($haystack,$replace,$pos,strlen($needle));
}
strlen($replace) 대신 strlen($needle)을 적어 둡니다.좀바트의 예는 바늘과 교체의 길이가 같은 경우에만 올바르게 작동합니다.
다음은 PHP의 str_replace와 동일한 시그니처를 가진 함수의 동일한 기능입니다.
function str_replace_first($search, $replace, $subject) {
$pos = strpos($subject, $search);
if ($pos !== false) {
return substr_replace($subject, $replace, $pos, strlen($search));
}
return $subject;
}
다음은 'too much php'의 수정된 답변입니다.
implode($replace, explode($search, $subject, 2));
끝에 1이 아닌 2를 적어 둡니다.또는 함수 형식:
function str_replace_first($search, $replace, $subject) {
return implode($replace, explode($search, $subject, 2));
}
두 기능의 타이밍을 맞췄는데 첫 번째 함수는 일치하는 함수가 없을 때 두 배로 빨라집니다.일치하는 것이 발견되었을 때와 같은 속도입니다.
어떤 게 제일 빠른지 궁금해서 다 테스트해봤어요.
이하에 기재되어 있습니다.
- 이 페이지에 게재된 모든 기능의 포괄적인 리스트
- 각 구성에 대한 벤치마크 테스트(평균 실행 시간 10,000회 이상)
- 각 답변에 대한 링크(전체 코드)
모든 기능이 동일한 설정으로 테스트되었습니다.
$string = 'OOO.OOO.OOO.S';
$search = 'OOO';
$replace = 'B';
문자열 내의 첫 번째 문자열만 대체하는 함수:
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%
문자열 내의 마지막 문자열만 대체하는 함수:
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%
유감스럽게도, 저는 이것을 할 수 있는 PHP 함수는 모릅니다.
다음과 같이 간단하게 자신의 것을 롤할 수 있습니다.
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));
}
Regexp 없이 문자열(대문자와 소문자가 구분됨)의 문자열을 제한으로 대체하는 이 작은 함수를 만들었습니다.잘 되고 있어요.
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;
}
사용 예:
$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
$str = "/property/details&id=202&test=123#tab-6p";
$position = strpos($str,"&");
echo substr_replace($str,"?",$position,1);
substrate_replace를 사용하면 문자열 내에서만 첫 번째 문자를 대체할 수 있습니다. &은 여러 번 반복되지만 첫 번째 위치에서만 &로 대체해야 합니다.
=> 코드가 수정되었으므로 일부 코멘트는 너무 오래되었다고 생각하십시오.
그리고 제가 그걸 개선할 수 있도록 도와준 모든 분들께 감사드립니다.
BUG가 있으면 연락 주세요.바로 수정해 드리겠습니다.
그럼 다음으로 넘어가겠습니다.
첫 번째 'o'를 'ea'로 치환하는 예:
$s='I love you';
$s=str_replace_first('o','ea',$s);
echo $s;
//output: I leave you
기능:
function str_replace_first($this,$that,$s)
{
$w=strpos($s,$this);
if($w===false)return $s;
return substr($s,0,$w).$that.substr($s,$w+strlen($this));
}
가장 쉬운 방법은 정규 표현을 사용하는 것입니다.
다른 방법은 strpos()를 사용하여 문자열 위치를 찾은 다음 subst_replace()를 사용하여 문자열 위치를 찾는 것입니다.
하지만 저는 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));
}
$string = 'this is my world, not my world';
$find = 'world';
$replace = 'farm';
$result = preg_replace("/$find/",$replace,$string,1);
echo $result;
@renocor의 답변을 확대하기 위해 100% 역호환 기능을 작성했습니다.str_replace()
즉, 의 모든 항목을 치환할 수 있습니다.str_replace()
str_replace_limit()
어레이를 사용하는 사용자도 문제 없이$search
,$replace
, "/"$subject
.
함수 호출을 다음과 같이 치환하는 경우 함수는 완전히 자급자족할 수 있습니다.($string===strval(intval(strval($string))))
valid_integer()
는 문자열로 제공되는 정수를 처리할 때 상당히 유용한 함수입니다.
주의:str_replace_limit()
str_replace()
대신, 「」에의 콜이,str_replace()
로 할 수 str_replace_limit()
퍼포먼스에 영향을 주지 않습니다.
사용.
<?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개의 교환 - bbbc
$limit = 1; // Limit of 1
$new_string = str_replace_limit($search, $replace, $subject, $count, $limit);
echo $count.' replacements -- '.$new_string;
교환품 1개 --bcabc
$limit = 10; // Limit of 10
$new_string = str_replace_limit($search, $replace, $subject, $count, $limit);
echo $count.' replacements -- '.$new_string;
2개의 교환 - bbbc
기능.
<?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;
}
}
제 테스트 결과에 따르면, 저는 카림79가 제공하는 regular_express에 투표하고 싶습니다.(지금 투표하기에는 평판이 부족합니다!)
좀바트의 솔루션은 함수 호출을 너무 많이 사용하여 코드도 단순화했습니다.PHP 5.4를 사용하여 두 솔루션을 모두 100,000회 실행 중입니다. 결과는 다음과 같습니다.
$str = 'Hello abc, have a nice day abc! abc!';
$pos = strpos($str, 'abc');
$str = substr_replace($str, '123', $pos, 3);
==> 1.85초
$str = 'Hello abc, have a nice day abc! abc!';
$str = preg_replace('/abc/', '123', $str, 1);
==> 1.35초
당신이 볼 수 있듯이.preg_replace의 성능은 많은 사람들이 생각하는 것만큼 나쁘지 않습니다.그래서 일반 표현이 복잡하지 않다면 고급스러운 해결책을 제안합니다.
을.$limit
바꿀 발생 횟수를 지정하는 매개 변수입니다.
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;
}
}
}
문자열의 경우
$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
1글자의 경우
$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
다른 사람의 말을 보완하기 위해 문자열 전체가 배열임을 기억하십시오.
$string = "Lorem ipsum lá lá lá";
$string[0] = "B";
echo $string;
"보렘 입숨 라 라 라 라"
이 함수는 @renocor의 답변에서 많은 영감을 받았습니다.이것은 함수를 수 바이트로 안전하게 만듭니다.
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;
}
다음을 사용할 수 있습니다.
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;
}
이 예는 php.net 에서 찾았습니다.
사용방법:
$string = "Thiz iz an examplz";
var_dump(str_replace_once('z','Z', $string));
출력:
ThiZ iz an examplz
이로 인해 성능이 다소 저하될 수 있지만 가장 쉬운 해결책입니다.
루프 솔루션의 경우
<?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;
}
대신 프레그를 사용하겠습니다.1로 설정할 수 있는 LIMIT 파라미터가 있습니다.
preg_replace (regex, subst, string, limit) // default is -1
$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")
추가 공간이 하나 더 있지만 제 경우에는 백게이트 스크립트이기 때문에 문제가 되지 않았습니다.
문자열에 멀티바이트 문자가 포함되어 있지 않은 경우, 1개의 문자만 치환하고 싶은 경우는, 간단하게 사용할 수 있습니다.
여기서 오류를 처리하는 함수
/**
* 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;
}
다음은 약간 변경된 str_replace() 함수를 정리하기 위해 만든 간단한 클래스입니다.
php::str_rreplace() 함수를 사용하면 문자열의 마지막 X개의 인스턴스만 바꾸려고 할 때 매우 편리합니다.
이러한 예에서는 둘 다 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) );
}
}
언급URL : https://stackoverflow.com/questions/1252693/using-str-replace-so-that-it-only-acts-on-the-first-match
'programing' 카테고리의 다른 글
Wordpress에서의 커스텀쿼리 실행에 문제가 있는 경우 (0) | 2023.01.24 |
---|---|
클래스의 최종 정적 필드 값은 어떻게 참조할 수 있습니까? (0) | 2023.01.24 |
Ubuntu의 MySQL JDBC jar 파일은 어디에 있습니까? (0) | 2023.01.14 |
MySQL이 NULL이 아니면 1을 표시하고, 그렇지 않으면 0을 표시합니다. (0) | 2023.01.14 |
오늘 날짜에 일수를 추가하는 방법은 무엇입니까? (0) | 2023.01.14 |