substr_replace
(PHP 4, PHP 5, PHP 7, PHP 8)
substr_replace — 文字列の一部を置換する
説明
array|string
$string
,array|string
$replace
,array|int
$offset
,array|int|null
$length
= null
): string|array
substr_replace()は、文字列
string
の offset
および
(オプションの) length
パラメータで区切られた部分を
replace
で指定した文字列に置換します。
パラメータ
string
-
入力文字列。
文字列の配列を指定することもでき、各文字列について順に置換を行います。 この場合、他のパラメータ
replace
、offset
およびlength
がスカラ値なら それを各入力文字列に順次適用し、配列なら各入力文字列に対応する要素の値を適用します。 replace
-
置換する文字列。
offset
-
offset
が負ではない場合、置換はstring
でoffset
番目の文字から始まります。offset
が負の場合、置換はstring
の終端からoffset
番目の文字から始まります。 length
-
正の値を指定した場合、
string
の置換される部分の長さを表します。 負の場合、置換を停止する位置がstring
の終端から何文字目であるかを表します。このパラメータが省略された場合、 デフォルト値は strlen(string
)、すなわち、string
の終端まで置換することになります。 当然、もしlength
がゼロだったら、 この関数はstring
の最初からoffset
の位置にreplace
を挿入するということになります。
戻り値
結果の文字列を返します。もし、string
が配列の場合、配列が返されます。
変更履歴
バージョン | 説明 |
---|---|
8.0.0 |
length は、nullable になりました。
|
例
例1 シンプルな substr_replace() の例
<?php
$var = 'ABCDEFGH:/MNRPQR/';
echo "Original: $var<hr />\n";
/* 以下の2つの例は、全ての $var で 'bob' で置換します。 */
echo substr_replace($var, 'bob', 0) . "<br />\n";
echo substr_replace($var, 'bob', 0, strlen($var)) . "<br />\n";
/* $var の先頭に 'bob' を挿入します */
echo substr_replace($var, 'bob', 0, 0) . "<br />\n";
/* 次の2つの例は、$var の 'MNRPQR' を 'bob'で置換します */
echo substr_replace($var, 'bob', 10, -1) . "<br />\n";
echo substr_replace($var, 'bob', -7, -1) . "<br />\n";
/* $var から 'MNRPQR' を削除します */
echo substr_replace($var, '', 10, -1) . "<br />\n";
?>
例2 substr_replace() で複数の文字列を一度に置換する例
<?php
$input = array('A: XXX', 'B: XXX', 'C: XXX');
// シンプルなケース: 各文字列の XXX を YYY で置換します
echo implode('; ', substr_replace($input, 'YYY', 3, 3))."\n";
// より複雑で、各文字列で置換する値が異なるケース
$replace = array('AAA', 'BBB', 'CCC');
echo implode('; ', substr_replace($input, $replace, 3, 3))."\n";
// 置換する文字数が異なるケース
$length = array(1, 2, 3);
echo implode('; ', substr_replace($input, $replace, 3, $length))."\n";
?>
上の例の出力は以下となります。
A: YYY; B: YYY; C: YYY A: AAA; B: BBB; C: CCC A: AAAXX; B: BBBX; C: CCC
注意
注意: この関数はバイナリデータに対応しています。
User Contributed Notes 32 notes
It's worth noting that when start and length are both negative -and- the length is less than or equal to start, the length will have the effect of being set as 0.
<?php
substr_replace('eggs','x',-1,-1); //eggxs
substr_replace('eggs','x',-1,-2); //eggxs
substr_replace('eggs','x',-1,-2); //eggxs
?>
Same as:
<?php
substr_replace('eggs','x',-1,0); //eggxs
?>
<?php
substr_replace('huevos','x',-2,-2); //huevxos
substr_replace('huevos','x',-2,-3); //huevxos
substr_replace('huevos','x',-2,-3); //huevxos
?>
Same as:
<?php
substr_replace('huevos','x',-2,0); //huevxos
?>
Another note, if length is negative and start offsets the same position as length, length (yet again) will have the effect as being set as 0. (Of course, as mentioned in the manual, when length is negative it actually represents the position before it)
<?php
substr_replace('abcd', 'x', 0, -4); //xabcd
?>
Same as:
<?php
substr_replace('abcd','x',0,0); //xabcd
?>
<?php
substr_replace('abcd', 'x', 1, -3); //axbcd
?>
Same as:
<?php
substr_replace('abcd', 'x', 1, 0); //axbcd
?>
Add prefix to strings:
<?php
substr_replace($strings, '_prefix', 0, 0);
?>
Add suffix/postfix to strings:
<?php
substr_replace($strings, '_suffix', array_map('strlen', $strings), 0);
?>
Forget all of the mb_substr_replace() implementations mentioned in this page, they're all buggy.
Here is a version that mimics the behavior of substr_replace() exactly:
<?php
if (function_exists('mb_substr_replace') === false)
{
function mb_substr_replace($string, $replacement, $start, $length = null, $encoding = null)
{
if (extension_loaded('mbstring') === true)
{
$string_length = (is_null($encoding) === true) ? mb_strlen($string) : mb_strlen($string, $encoding);
if ($start < 0)
{
$start = max(0, $string_length + $start);
}
else if ($start > $string_length)
{
$start = $string_length;
}
if ($length < 0)
{
$length = max(0, $string_length - $start + $length);
}
else if ((is_null($length) === true) || ($length > $string_length))
{
$length = $string_length;
}
if (($start + $length) > $string_length)
{
$length = $string_length - $start;
}
if (is_null($encoding) === true)
{
return mb_substr($string, 0, $start) . $replacement . mb_substr($string, $start + $length, $string_length - $start - $length);
}
return mb_substr($string, 0, $start, $encoding) . $replacement . mb_substr($string, $start + $length, $string_length - $start - $length, $encoding);
}
return (is_null($length) === true) ? substr_replace($string, $replacement, $start) : substr_replace($string, $replacement, $start, $length);
}
}
?>
PHP version of Java's removeCharAt() function:
<?php
function removeCharAt($str, $int){
return substr_replace($str,"",$int,1);
}
?>
Using substr_replace() can be avoided by using substr() instead:
<?
$string = substr($string, 0, $position_needle).$replace.substr($string, $position_needle+$length_needle);
?>
This can be useful when you need to replace parts of multibyte strings like strings encoded with utf-8. There isn't a multibute variant for substr_replace(), but for php substr() there is mb_substr(). For more information on multibyte strings see http://nl3.php.net/manual/en/ref.mbstring.php
I have a little function that works like substr_replace () what I use for some purpose. Maybe someone needs it.
<?php
function putinplace($string=NULL, $put=NULL, $position=false)
{
$d1=$d2=$i=false;
$d=array(strlen($string), strlen($put));
if($position > $d[0]) $position=$d[0];
for($i=$d[0]; $i >= $position; $i--) $string[$i+$d[1]]=$string[$i];
for($i=0; $i<$d[1]; $i++) $string[$position+$i]=$put[$i];
return $string;
}
// Explanation
$string='My dog dont love postman'; // string
$put="'"; // put ' on position
$position=10; // number of characters (position)
print_r( putinplace($string, $put, $position) );
?>
RESULT: My dog don't love postman
This is a small powerful function that performs its job flawlessly.
This will truncate a longer string to a smaller string of specified length while replacing the middle portion with a separator exactly in the middle.
<?php
$longString = 'abcdefghijklmnopqrstuvwxyz0123456789z.jpg';
$separator = '/.../';
$separatorlength = strlen($separator) ;
$maxlength = 25 - $separatorlength;
$start = $maxlength / 2 ;
$trunc = strlen($longString) - $maxlength;
echo substr_replace($longString, $separator, $start, $trunc);
//prints "abcdefghij/.../56789z.jpg"
?>
I imagine the description of the parameters really means "number of bytes" where it says "number of characters" (confirmed by testing).
I've just taken a look at the post by ntoniazzi and I have a very small correction to make.
In the second if statement, it should be a triple equals, so:
<?php if ($length === null) ?>
It requires the triple equals, for the case of pure insertion, where $length = 0, the double equals, will catch this, causing the string to be cut short. I hope this helps someone.
I recently ran across a situation where I need to strip a heavily nested html list such that only the top level was preserved. I started with a regular expression solution, but found that I kept matching the wrong closing ul with an outer opening ul.
This was my alternative solution, and it seems to work well:
<?php
function stripNestedLists($str)
{
$str2 = $str;
$lastStr = $str2;
do
{
// Find the first closing ul
$cul = strpos($str2, '</ul>');
$ul = 0;
$lastUL = 0;
do
{
// Find the next opening ul
$lastUL = $ul;
$ul = strpos($str2, '<ul', $ul+1);
}
while ($ul !== false && $ul < $cul);
$lastStr = $str2;
$str2 = substr_replace($str2, '', $lastUL, $cul-$lastUL+5);
$str2 = trim($str2);
}
while (strlen($str2) > 0);
return $lastStr;
}
?>
Hope this helps someone.
THE DOT DOT DOT ISSUE
PROBLEM:
You want to abbreviate a string.
E.g. You want "BritneySpears" to show as "BritneySpe...", being only the ten first characters followed by "..."
SOLUTION:
<?
$oRIGINAL = "BritneySpears";
$sHORTER = substr_replace($oRIGINAL, '...', 10);
echo ($sHORTER);
?>
This will result in BritneySpe...
I like the truncate function below...however, I found a few issues. Particularly if you have content that may have any kind of punctuation in it (?, !, ?!?, --, ..., .., ;, etc.)
The older function would end up looking like "blah blah?..." or "blah blah,..." which doesn't look so nice to me...
Here's my fix. It removes all trailing punctuation (that you include in the $punctuation string below) and then adds an ellipse. So even if it has an ellipse with 3 dots, 2 dots, 4 dots, it'll be removed, then re-added.
<?php
function truncate($text,$numb,$etc = "...") {
$text = html_entity_decode($text, ENT_QUOTES);
if (strlen($text) > $numb) {
$text = substr($text, 0, $numb);
$text = substr($text,0,strrpos($text," "));
$punctuation = ".!?:;,-"; //punctuation you want removed
$text = (strspn(strrev($text), $punctuation)!=0)
?
substr($text, 0, -strspn(strrev($text), $punctuation))
:
$text;
$text = $text.$etc;
}
$text = htmlentities($text, ENT_QUOTES);
return $text;
}
?>
I also needed a sort of "middle" truncate. The above function truncates around the end, but if you want to truncate around the middle (ie "Hello this is a long string." --> "Hello this ... long string.") you can use this (requires the truncate function):
<?php
function mtruncate($text, $numb, $etc = " ... ") {
$first_part = truncate(truncate($text, strlen($text)/2, ""), $numb/2, "");
$second_part = truncate(strrev(truncate(strrev($text), strlen($text)/2, "")), $numb/2, "");
return $first_part.$etc.$second_part;
}
?>
If your string is not long enough to meet what you specify in start and length then the replacement string is added towards the end of the string.
I wanted to replace the end of the string with ... if the string was too long to display (for instance article preview on a website). The problem was that my string was sometimes not that long and it still added the replacement string. So I wrote a function to replace substr_replace in my website:
function add_3dots($string,$repl,$start,$limit) {
if(strlen($string) > $limit) {
return substr_replace(strip_tags($string),$repl,$start,$limit);
} else {
return $string;
};
};
I use strip_tags to strip out the HTML otherwise you might get a screwed up HTML (when a tags open in the string, but because you cut-off it doesn't)