2024 年 PHP Conference Japan

substr_replace

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

substr_replace取代字串一部分的文字

描述

substr_replace(
    陣列|字串 $string,
    陣列|字串 $replace,
    陣列|整數 $offset,
    (陣列|整數|null $length = null)
): 字串|陣列

substr_replace() 會將 string 中由 offset 和(可選的)length 參數界定的部分複製後,以 replace 中提供的字串取代。

參數

string

輸入字串。

可以提供一個 字串陣列,在這種情況下,會依次對每個字串進行替換。此時,replaceoffsetlength 參數可以提供為純量值,以便依次應用於每個輸入字串,或者也可以提供為 陣列,在這種情況下,將使用對應的陣列元素來處理每個輸入字串。

replace

取代字串。

offset

如果 offset 為非負數,則替換將從 string 中的第 offset 個偏移量開始。

如果 offset 為負數,則替換將從 string 尾端的第 offset 個字元開始。

length

如果給定且為正數,則表示要替換的 string 部分的長度。如果為負數,則表示從 string 尾端算起停止替換的字元數。如果未給定,則預設為 strlen( string );也就是說,在 string 的結尾處結束替換。當然,如果 length 為零,則此函式的作用是在給定的 offset 偏移量處將 replace 插入 string

返回值

返回結果字串。如果 string 是一個陣列,則返回陣列。

更新日誌

版本 描述
8.0.0 length 現在可以為 null。

範例

範例 #1 簡單的 substr_replace() 範例

<?php
$var
= 'ABCDEFGH:/MNRPQR/';
echo
"原始字串: $var<hr />\n";

/* 這兩個範例會將 $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";

/* 接下來的兩個範例會將 $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

注意事項

注意此函式是二進位安全的。

參見

新增註解

使用者貢獻的註解 32 則註解

elloromtz at gmail dot com
14 年前
值得注意的是,當起始位置和長度皆為負數,且長度小於或等於起始位置時,長度的效果將被設為 0。

<?php
substr_replace
('eggs','x',-1,-1); //eggxs
substr_replace('eggs','x',-1,-2); //eggxs
substr_replace('eggs','x',-1,-2); //eggxs
?>

與以下相同
<?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
?>

與以下相同
<?php
substr_replace
('huevos','x',-2,0); //huevxos
?>

另一個注意事項是,如果長度為負數且起始偏移量與長度相同的位置,則長度(再次)將具有如同設定為 0 的效果。(當然,如手冊中所述,當長度為負數時,它實際上代表它之前的位置)

<?php
substr_replace
('abcd', 'x', 0, -4); //xabcd
?>

與以下相同
<?php
substr_replace
('abcd','x',0,0); //xabcd
?>

<?php
substr_replace
('abcd', 'x', 1, -3); //axbcd
?>

與以下相同
<?php
substr_replace
('abcd', 'x', 1, 0); //axbcd
?>
shaman_master at list dot ru
4 年前
為字串添加前綴
<?php
substr_replace
($strings, '_prefix', 0, 0);
?>
為字串添加後綴
<?php
substr_replace
($strings, '_suffix', array_map('strlen', $strings), 0);
?>
billg AT microsoft.com
15 年前
忘記這個頁面上提到的所有 mb_substr_replace() 實作,它們都有錯誤。

這是一個完全模仿 substr_replace() 行為的版本

<?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);
}
}

?>
eblejr AT phrebh DOT com
16 年前
Java 的 removeCharAt() 函式的 PHP 版本

<?php
function removeCharAt($str, $int){
return
substr_replace($str,"",$int,1);
}
?>
danieldoorduin at hotmail dot com
19 年前
可以使用 substr() 來避免使用 substr_replace()

<?
$string = substr($string, 0, $position_needle).$replace.substr($string, $position_needle+$length_needle);
?>

當您需要替換多位元組字串(例如以 utf-8 編碼的字串)的某些部分時,這會很有用。 substr_replace() 沒有多位元組的變體,但 php substr() 有 mb_substr()。有關多位元組字串的更多資訊,請參閱 http://nl3.php.net/manual/en/ref.mbstring.php
ivijan dot stefan at gmail dot com
10 年前
我有一個類似 substr_replace () 的小函式,可以用於某些目的。也許有人需要它。

<?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;
}

// 說明
$string='My dog dont love postman'; // 字串
$put="'"; // 在指定位置插入 '
$position=10; // 字元數量 (位置)
print_r( putinplace($string, $put, $position) );
?>

結果:My dog don't love postman

這是一個小巧強大的函式,可以完美地執行它的任務。
kalim dot fleet at gmail dot com
15 年前
這會將較長的字串截斷為指定長度的較短字串,同時將中間部分替換為恰好位於中間的分隔符號。

<?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);

//印出 "abcdefghij/.../56789z.jpg"

?>
bkline at rksystems dot com
5 年前
我認為參數說明中寫的「字元數」實際上指的是「位元組數」(經測試確認)。
juichenieder-phnet at yahoo dot co dot uk
15 年前
我剛看了 ntoniazzi 的文章,並發現一個小錯誤需要更正。

在第二個 if 陳述句中,應該使用三個等號,所以程式碼應為:

<?php if ($length === null) ?>

需要使用三個等號是因為在純粹插入的情況下,$length = 0,使用兩個等號會將此情況也納入,導致字串被截斷。希望這對大家有所幫助。
Hayley Watson
7 年前
如果您想對陣列執行這類操作,請參考 array_splice 函式。
William Barry
16 年前
我最近遇到一個情況,需要去除一個深度巢狀的 HTML 清單,使其只保留最上層。我一開始嘗試使用正規表示式,但發現我總是將錯誤的 ul 結束標籤與外部的 ul 開始標籤匹配。

這是我的替代方案,而且似乎運作良好。

<?php

函式 stripNestedLists($str)
{
$str2 = $str;
$lastStr = $str2;

do
{
// 尋找第一個 ul 結束標籤
$cul = strpos($str2, '</ul>');
$ul = 0;
$lastUL = 0;
do
{
// 尋找下一個 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;
}

?>

希望這對某些人有幫助。
klaas at group94 dot com
22 年前
省略號問題

問題
您想要縮短一個字串。
例如,您想要將 "BritneySpears" 顯示為 "BritneySpe...",只顯示前十個字元,後面接著 "..."

解決方案
<?
$oRIGINAL = "BritneySpears";
$sHORTER = substr_replace($oRIGINAL, '...', 10);
echo ($sHORTER);
?>

這將會產生 BritneySpe...
alishahnovin at hotmail dot com
17 年前
我喜歡下面的 truncate 函式... 然而,我發現了一些問題。尤其是當您的內容中可能包含任何標點符號時(?、!、?!、--、...、..、; 等等)

舊的函式最終會看起來像 "blah blah?..." 或 "blah blah,...",在我看來不太好看...

這是我的修正。它會移除所有結尾的標點符號(您將其包含在下面的 $punctuation 字串中),然後新增一個省略號。因此,即使它有一個包含 3 個點、2 個點、4 個點的省略號,它也會被移除,然後重新新增。

<?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 = ".!?:;,-"; // 要移除的標點符號

$text = (strspn(strrev($text), $punctuation)!=0)
?
substr($text, 0, -strspn(strrev($text), $punctuation))
:
$text;

$text = $text.$etc;
}
$text = htmlentities($text, ENT_QUOTES);
return
$text;
}
?>

我也需要一種「中間截斷」的功能。上述函式會在尾端截斷,但如果您想在中間截斷(例如「Hello this is a long string.」變成「Hello this ... long string.」),您可以使用這個函式(需要 truncate 函式)

<?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;
}
?>
大師 Evi
19 年前
如果您的字串長度不足以滿足您在起始位置和長度中指定的內容,則替換字串會被添加到字串的末尾。

如果字串太長而無法顯示(例如網站上的文章預覽),我想用 ... 替換字串的結尾。問題是我的字串有時並不是很長,它仍然添加了替換字串。所以我寫了一個函式來替換我網站中的 substr_replace

function add_3dots($string,$repl,$start,$limit) {
if(strlen($string) > $limit) {
return substr_replace(strip_tags($string),$repl,$start,$limit);
} else {
return $string;
};
};

我使用 strip_tags 去除 HTML 標籤,否則您可能會得到一個混亂的 HTML(當標籤在字串中打開,但因為您截斷了它,所以沒有關閉)
hermes at andycostell dot com
19 年前
我建議稍微修改 Guru Evi 建議的函式。我發現它在這裡的寫法不起作用。

原始版本
function add_3dots($string,$repl,$start,$limit) {
if(strlen($string) > $limit) {
return substr_replace(strip_tags($string),$repl,$start,$limit);
} else {
return $string;
};
};

我的建議
function add_3dots($string,$repl,$limit) {
if(strlen($string) > $limit) {
return substr_replace(strip_tags($string),$repl,$limit-strlen($repl));
} else {
return $string;
}
}

用法

$max_length=10;//您想要顯示的最大字元數
$too_long_string="BLAH BLAH BLAH BLAH BLAH etc.";//您想要縮短的字串(如果它比 $limit 長)
$shorter_string=add_3_dots($too_long_string,"...",$max_length);
yeyijelud at amadamus dot com
6 年前
第一個例子可以簡化 =>

$input = array('A: XXX', 'B: XXX', 'C: XXX');

substr_replace($input, 'YYY', -3);

輸出:Array ( [0] => A: YYY [1] => B: YYY [2] => C: YYY )
meg dot phillips91 at gmail dot com
4 年前
這對其他人來說可能很明顯,但我花了好幾個小時,我的腦袋在休息了很長時間後才明白。

如果您正在循環一個有多個需要替換的子字串的字串,則在替換任何字串之前,您必須為每個原始偏移量添加一個偏移因子。以下是一個實際的例子

從 draft.js 我們得到帶有多個連結的段落,這些連結僅用偏移量、錨文本長度、網址、目標來指定。因此,每個錨文本都必須包含在 <a href="url" target="target">anchortext</a> 中,以便在資料庫中儲存正確的內容。

以下是偏移因子的實作

$offset_factor = 0;

foreach($content->links->links as $index=>$link){
$replacement = '<a href="'.$link->href.'" target="$link->target">'.$link->anchorText.'</a>';
$new_offset = $link->offset + $offset_factor;
$newtext = \substr_replace($content->text, $replacement, $new_offset, $link->length);

//現在我們用 newtext 重設原始段落文字
$content->text = $newtext;

//通過計算替換長度和原始長度之間的差異來計算新的偏移量,並將其添加到 offset_factor 中
$additional_characters = strlen($replacement) - $link->length;
$offset_factor = $offset_factor + $additional_characters;
}

我希望這對新手有所幫助 :) 如果有其他更簡單的方法,我很樂意聽到。
nospam at nospam dot com
8 年前
<?php

// shortens a long string to a max length while inserting a string into the exact middle
function strShorten($str, $maxlen = 10, $insert = '/.../') {
if (
$str && !is_array($str)) { // valid string
if ($maxlen && is_numeric($maxlen) && $maxlen < strlen($str)) { // string needs shortening
if ($insert && ($ilen = strlen($insert))) { // insert string and length
if ($ilen >= $maxlen) { // insert string too long so use default insert
$insert = '**'; // short default so works even when a very small $maxlen
$ilen = 2;
}
}
$chars = $maxlen - $ilen; // number of $str chars to keep
$start = ceil($chars/2); // position to start cutting
$end = floor($chars/2); // position from end to stop cutting
return substr_replace($str, $insert, $start, -$end); // first.insert.last
} else { // string already short enough
return $str; // return original string
}
}
}

echo
strShorten('123456789', 6, ''); // outputs 123789
echo strShorten('123456789', 6, '-'); // outputs 123-89
echo strShorten('123456789', 6, 'longstring'); // outputs 12**89
echo strShorten('abcdefghijklmnopqrstuvwxyz', 10, '..'); // outputs abcd..wxyz
echo strShorten('abcdefghijklmnopqrstuvwxyz'); // outputs abc/.../yz

?>
NiX0n at fragfest dot cx
16 年前
用於預先測試 $string 是否「過長」的程式碼不應該將 strlen($replacement) 加到 $max 中。$max 應該代表回傳字串的絕對最大長度。在判斷長度時,$replacement 的大小無關緊要。

函式的其餘部分(下方未變更)的操作如上所述。也就是說,$replacement 的大小會從 $max 中減去,以便回傳的字串長度正好等於 $max。

<?php
function truncate($string, $max = 20, $replacement = '')
{
if (
strlen($string) <= $max)
{
return
$string;
}
$leave = $max - strlen ($replacement);
return
substr_replace($string, $replacement, $leave);
}
?>
jaimthorn at yahoo dot com
16 年前
我最近需要一個常式,可以從一個字串中移除另一個字串中的字元,就像這個正規表達式一樣

<?php
$result
= preg_replace("/[$chars]/", "", $string);
?>

而且我需要它執行速度快,並且能接受幾乎所有輸入。當 strlen($chars) == 0 時,上面的正規表達式將無法正常運作。我想出了這個,不得不承認看起來很糟的程式碼,但它的執行速度相當快

<?php

function RemoveChars($string, $chars)
{
return isset(
$chars{0}) ? str_replace($chars{0}, "", strtr($string, $chars, str_pad($chars{0}, strlen($chars), $chars{0}))) : $string;
}

?>

根據我自己的測量,只有當 strlen($chars) == 1 時,正規表達式的速度才會比較快;對於較長的字串,我的常式速度比較快。它是怎麼做的?假設您想從字串中移除句點、逗點和驚嘆號,如下所示
$result = RemoveChars("Isn't this, like, totally neat..!?", ".?!");
`str_pad` 函式會建立一個與包含要移除之字元的字串長度相等的字串,但該字串僅由該字串的第一個字元組成
輸入是 ".,!"
輸出是 "..."
`strtr` 函式會將要處理的字串 ("Isn't this...") 中也出現在輸入 (".,!") 中的所有字元轉換為輸出 ("...") 中相同位置的字元。換句話說
Isn't this, like, totally neat..!?
會變成
Isn't this. like. totally neat....
最後,輸入字串 (".,!") 中的第一個字元,也就是句點,再次透過 str_replace 呼叫從該字串中移除。
這不是很棒嗎?
這個函式需要檢查 $chars 是否至少包含一個字元,否則 str_pad 函式會失敗。如果它是空的,則會返回未處理的字串。
chuayw2000 at hotmail dot com
18 年前
我不確定這個函式是否支援多位元組,但我寫了一個在多位元組模式下也能運作的函式。

<?php
// 檢查是否存在,以防 PHP 之後新增了這個函式
if (!function_exists("mb_substr_replace")){
// 與 substr_replace 相同的參數,加上額外的編碼參數。
function mb_substr_replace($string,$replacement,$start,$length=null,$encoding = null){
if (
$encoding == null){
if (
$length == null){
return
mb_substr($string,0,$start).$replacement;
}
else{
return
mb_substr($string,0,$start).$replacement.mb_substr($string,$start + $length);
}
}
else{
if (
$length == null){
return
mb_substr($string,0,$start,$encoding).$replacement;
}
else{
return
mb_substr($string,0,$start,$encoding). $replacement. mb_substr($string,$start + $length,mb_strlen($string,$encoding),$encoding);
}
}
}
}
?>
dmron
20 年前
關於「...」,即使是簡短的函式也過於冗長和複雜,而且沒有必要使用 substr_replace。 正如下方發文者所述,在 4.3.5 之前的版本中,substr() 效果更好,速度也快得多。

function shorten( $str, $num = 100 ) {
if( strlen( $str ) > $num ) $str = substr( $str, 0, $num ) . "...";
return $str;
}
geniusdex (at) brz (dot) nu
20 年前
這是我的 dotted 字串製作版本

<?php
function dot($str, $len, $dots = "...") {
if (
strlen($str) > $len) {
$dotlen = strlen($dots);
substr_replace($str, $dots, $len - $dotlen);
}
}
?>
david at ethinkn dot com
21 年前
這是一個簡化字串並加上省略號的簡單函式

<?php

/**
* truncate() 簡化字串並加上省略號的簡單函式
*
* @param string $string 原始字串
* @param integer $max 最大長度
* @param string $rep 取代的字串... (預設 = '' - 無省略號 -)
* @return string
* @author David Duong
**/
function truncate($string, $max = 50, $rep = '') {
$leave = $max - strlen($rep);
return
substr_replace($string, $rep, $leave);
}

echo
truncate('akfhslakdhglksjdgh', 10, '...');
// 回傳 akfhsla... (10 個字元)

?>
mrbrown8 at juno dot com
23 年前
補充一下這些例子,如果取代字串的長度大於指定長度,則只會從原始字串中移除指定長度的字元,並將整個取代字串放入其位置,因此 strlen($string) 的值會增加。

$var = 'ABCDEFGH:/MNRPQR/';
/* 應該回傳 ABCDEFGH:/testingRPQR/ */
echo substr_replace ($var, 'testing', 10, 2);
den dot gierling at web dot de
14 年前
我的問題是 substr_replace() 總是會加上 $replacement,所以我寫了自己的函式。
這個函式只有在 substr() 執行後才會加上 $replacement。
參數 $length 是可選的,就像 substr() 一樣。
或者是我在使用 $start 和 $length 時太笨了...

<?php
function substr_replace_provided($string,$replacement,$start,$length=NULL)
{
$tmp=substr($string,$start,$length);
if(
$string!==$tmp) {
$string = $tmp.$replacement;
}
return
$string;
}
?>
Thijs Wijnmaalen (thijs[at]nllinux.nl)
20 年前
我寫了一個函式,例如您可以結合搜尋腳本使用它來截斷過長的字串 (文章)。

<?php
function substr_index($text, $maxChars = 20, $splitter
= '...') {

$theReturn = $text;
$lastSpace = false;

if (
strlen($text) > $maxChars) {
$theReturn = substr($text, 0, $maxChars - 1);

if (
in_array(substr($text, $maxChars - 1, 1),
array(
' ', '.', '!', '?'))) {
$theReturn .= substr($text, $maxChars, 1);
} else {
$theReturn = substr($theReturn, 0, $maxChars -
strlen($splitter));
$lastSpace = strrpos($theReturn, ' ');

if (
$lastSpace !== false) {
$theReturn = substr($theReturn, 0, $lastSpace);
}

if (
in_array(substr($theReturn, -1, 1), array(','))) {
$theReturn = substr($theReturn, 0, -1);
}
$theReturn .= $splitter;
}
}
return
$theReturn;
}
?>
spcl dot delivery at gmail dot com
16 年前
我前任的版本即使字串短於最大長度也會加上 $rep。這是修正後的版本。

<?php
function truncate($string, $max = 20, $rep = '')
{
if (
strlen($string) <= ($max + strlen($rep)))
{
return
$string;
}
$leave = $max - strlen ($rep);
return
substr_replace($string, $rep, $leave);
}
?>

若要保留檔案名稱的副檔名,您可以這樣呼叫它:

truncate([檔案名稱], 30, '...' . end(explode('.', [檔案名稱])))
匿名
23 年前
如果您想從字串的開頭或結尾移除字元,請嘗試使用 substr() 函式。

例如,要從字串中移除最後三個字元:
$string = "To be or not to be.";
$string = substr ($string, 0, -3);
blessador at gmail dot com
11 年前
<?php
$price
= "12000";
$price = substr_replace ($price, ',', -3, 0)";
?>

請務必移除上述程式碼中 substr_replace (
$price, ',', -3, 0)" 結尾的雙引號 " 以避免錯誤。
thomasNOSPAM at sportentranceNOSPAM dot com
22 年前
要將超出特定長度的連結縮寫為'...', 請使用 preg_replace 函式。

例如,您擷取了新聞網站的標題以在您自己的頁面上使用,但這些標題太長了

假設原始資料儲存在 $unedited 中;

$edited = preg_replace("/(>)([[:print:]]{52,})(<)/e", "'\\1'.substr_replace('\\2 ', '...', '48').'\\3'", $unedited);
echo $edited;

這會將超過 52 個字元的字串縮短為 51 個字元,最後三個字元是三個點...
olav at schettler dot net
9 年前
請注意,array_slice() 函式具有類似的功能,但適用於陣列而不是字串,其參數順序不同。
To Top