PHPのお勉強!

PHP TOP

substr_replace

(PHP 4, PHP 5, PHP 7, PHP 8)

substr_replace文字列の一部を置換する

説明

substr_replace(
    array|string $string,
    array|string $replace,
    array|int $offset,
    array|int|null $length = null
): string|array

substr_replace()は、文字列 stringoffset および (オプションの) length パラメータで区切られた部分を replace で指定した文字列に置換します。

パラメータ

string

入力文字列。

文字列の配列を指定することもでき、各文字列について順に置換を行います。 この場合、他のパラメータ replaceoffset および length がスカラ値なら それを各入力文字列に順次適用し、配列なら各入力文字列に対応する要素の値を適用します。

replace

置換する文字列。

offset

offset が負ではない場合、置換は stringoffset 番目の文字から始まります。

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

注意

注意: この関数はバイナリデータに対応しています。

参考

add a note

User Contributed Notes 32 notes

up
20
elloromtz at gmail dot com
14 years ago
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
?>
up
5
shaman_master at list dot ru
4 years ago
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);
?>
up
13
billg AT microsoft.com
15 years ago
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);
}
}

?>
up
5
eblejr AT phrebh DOT com
16 years ago
PHP version of Java's removeCharAt() function:

<?php
function removeCharAt($str, $int){
return
substr_replace($str,"",$int,1);
}
?>
up
7
danieldoorduin at hotmail dot com
20 years ago
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
up
6
ivijan dot stefan at gmail dot com
10 years ago
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.
up
4
kalim dot fleet at gmail dot com
15 years ago
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"

?>
up
1
bkline at rksystems dot com
5 years ago
I imagine the description of the parameters really means "number of bytes" where it says "number of characters" (confirmed by testing).
up
5
juichenieder-phnet at yahoo dot co dot uk
15 years ago
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.
up
3
Hayley Watson
7 years ago
See array_splice if you want to do this sort of thing to an array.
up
3
William Barry
16 years ago
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.
up
3
klaas at group94 dot com
22 years ago
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...
up
2
alishahnovin at hotmail dot com
17 years ago
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;
}
?>
up
1
Guru Evi
19 years ago
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)