PHP Conference Japan 2024

substr_replace

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

substr_replace替换字符串中的一部分文本

描述

substr_replace(
    数组|字符串 $string,
    数组|字符串 $replace,
    数组|整数 $offset,
    数组|整数| $length = null
): 字符串|数组

substr_replace() 使用 replace 中给定的字符串替换 string 的副本,该副本由 offset 和(可选)length 参数分隔。

参数

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 现在可以为空。

范例

示例 #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 年前
值得注意的是,当 start 和 length 都为负数 -并且- length 小于或等于 start 时,length 将会起到设置为 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
?>

另一个说明,如果 length 为负数并且 start 的偏移位置与 length 相同,length(再次)将起到设置为 0 的效果。(当然,如手册中所述,当 length 为负数时,它实际上表示其前面的位置)

<?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() 来避免使用 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

function 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 年前
我喜欢下面的截断函数...但是,我发现了一些问题。特别是如果您有包含任何标点符号的内容(?,!,?!,--,...,..,; 等)。

旧函数最终会显示为“blah blah?...”或“blah blah,...” ,在我看来这不太好看...

这是我的修复方法。它删除所有尾随标点符号(您在下面的 $punctuation 字符串中包含的),然后添加省略号。因此,即使它包含三个点、两个点或四个点的省略号,也会被删除,然后重新添加。

<?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;
}
?>
Guru 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 中,我们得到包含多个链接的段落,这些链接仅用偏移量、锚文本长度、URL 和目标来指定。因此,每个锚文本都必须包装在 <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

// 将长字符串缩短到最大长度,同时将字符串插入到中间
function strShorten($str, $maxlen = 10, $insert = '/.../') {
if (
$str && !is_array($str)) { // 有效字符串
if ($maxlen && is_numeric($maxlen) && $maxlen < strlen($str)) { // 字符串需要缩短
if ($insert && ($ilen = strlen($insert))) { // 插入字符串及其长度
if ($ilen >= $maxlen) { // 插入字符串太长,因此使用默认插入
$insert = '**'; // 简短的默认值,因此即使 $maxlen 很小也能工作
$ilen = 2;
}
}
$chars = $maxlen - $ilen; // 要保留的 $str 字符数
$start = ceil($chars/2); // 开始截取的位置
$end = floor($chars/2); // 从结尾停止截取的位置
return substr_replace($str, $insert, $start, -$end); // first.insert.last
} else { // 字符串已经足够短
return $str; // 返回原始字符串
}
}
}

echo
strShorten('123456789', 6, ''); // 输出 123789
echo strShorten('123456789', 6, '-'); // 输出 123-89
echo strShorten('123456789', 6, 'longstring'); // 输出 12**89
echo strShorten('abcdefghijklmnopqrstuvwxyz', 10, '..'); // 输出 abcd..wxyz
echo strShorten('abcdefghijklmnopqrstuvwxyz'); // 输出 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);
}
?>
[email protected]
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 调用从输入 (".,!") 中的第一个字符(再次是句点)中删除该字符串
Isn't this like totally neat?
该函数需要检查 $chars 是否至少包含一个字符,否则 str_pad 函数将失败。如果为空,则返回未处理的字符串。
[email protected]
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;
}
[email protected]
20年前
这是我制作带点字符串的版本

<?php
function dot($str, $len, $dots = "...") {
if (
strlen($str) > $len) {
$dotlen = strlen($dots);
substr_replace($str, $dots, $len - $dotlen);
}
}
?>
[email protected]
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 个字符)

?>
[email protected]
23年前
补充一下示例,如果替换字符串长度大于要替换的长度,则只从字符串中删除指定长度的字符,并将整个替换字符串放入其位置,因此 strlen($string) 会增加。

$var = 'ABCDEFGH:/MNRPQR/';
/* 应该返回 ABCDEFGH:/testingRPQR/ */
echo substr_replace ($var, 'testing', 10, 2);
[email protected]
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([filename], 30, '...' . end(explode('.', [filename])))
Anonymous
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