PHP Conference Japan 2024

strrpos

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

strrpos查找子字符串在字符串中最后一次出现的的位置

描述

strrpos(字符串 $haystack, 字符串 $needle, 整数 $offset = 0): 整数|false

查找 needlehaystack 字符串中最后一次出现的数字位置。

参数

haystack

要搜索的字符串。

needle

要搜索的字符串。

在 PHP 8.0.0 之前,如果 needle 不是字符串,则将其转换为整数并将其应用为字符的序数值。从 PHP 7.3.0 开始,此行为已弃用,强烈建议不要依赖它。根据预期的行为,needle 应该显式转换为字符串,或者应该显式调用 chr()

offset

如果为零或正数,则搜索从左到右执行,跳过 haystack 的前 offset 个字节。

如果为负数,则搜索从 haystack 的末尾开始向左偏移 offset 个字节,而不是从 haystack 的开头开始。搜索从右到左执行,从选定的字节开始搜索 needle 的第一次出现。

注意:

这实际上是在查找最后 offset 个字节中或之前 needle 的最后一次出现。

返回值

返回 needle 相对于 haystack 字符串开头的存在位置(与搜索方向或偏移量无关)。

注意: 字符串位置从 0 开始,而不是从 1 开始。

如果未找到 needle,则返回 false

警告

此函数可能返回布尔值 false,但也可能返回计算结果为 false 的非布尔值。有关更多信息,请阅读关于 布尔值 的部分。使用 === 运算符 测试此函数的返回值。

变更日志

版本 描述
8.0.0 needle 现在接受空字符串。
8.0.0 不再支持将 整数 作为 needle 传递。
7.3.0 整数 作为 needle 传递已弃用。

示例

示例 #1 检查针是否在干草堆中

很容易将返回值误认为“在位置 0 找到的字符”和“未找到的字符”。以下是如何检测差异

<?php

$pos
= strrpos($mystring, "b");
if (
$pos === false) { // 注意:三个等号
// 未找到...
}

?>

示例 #2 使用偏移量搜索

<?php
$foo
= "0123456789a123456789b123456789c";

// 从第 0 个字节(从开头)查找“0”
var_dump(strrpos($foo, '0', 0));

// 从第 1 个字节(在字节“0”之后)查找“0”
var_dump(strrpos($foo, '0', 1));

// 从第 21 个字节(在字节 20 之后)查找“7”
var_dump(strrpos($foo, '7', 20));

// 从第 29 个字节(在字节 28 之后)查找“7”
var_dump(strrpos($foo, '7', 28));

// 从右到左从末尾的第 5 个字节查找“7”
var_dump(strrpos($foo, '7', -5));

// 从右到左从末尾的第 2 个字节查找“c”
var_dump(strrpos($foo, 'c', -2));

// 从右到左从末尾的第 2 个字节查找“9c”
var_dump(strrpos($foo, '9c', -2));
?>

以上示例将输出

int(0)
bool(false)
int(27)
bool(false)
int(17)
bool(false)
int(29)

参见

  • strpos() - 查找子字符串在字符串中第一次出现的位置
  • stripos() - 查找不区分大小写的子字符串在字符串中第一次出现的位置
  • strripos() - 查找不区分大小写的子字符串在字符串中最后一次出现的位置
  • strrchr() - 在字符串中查找字符的最后一次出现
  • substr() - 返回字符串的一部分

添加注释

用户贡献的注释 30 条注释

brian at enchanter dot net
17 年前
“offset”的文档有误导性。

它说,“可以指定 offset 以开始搜索字符串中的任意数量的字符。负值将在字符串结束前的任意点停止搜索。”

如果你把 strrpos 想象成从字符串末尾开始反向查找,就会觉得很困惑。

理解 offset 的更好方法是

- 如果 offset 为正数,则 strrpos 只对从 offset 到字符串末尾的部分进行操作。这通常与不指定 offset 会得到相同的结果,除非 needle 仅出现在 offset 之前(在这种情况下,指定 offset 将找不到 needle)。

- 如果 offset 为负数,则 strrpos 只对字符串末尾的这么多字符进行操作。如果 needle 距离字符串末尾较远,则找不到它。

例如,如果你想查找第 50 个字符之前的最后一个空格,你需要执行以下操作

strrpos($text, " ", -(strlen($text) - 50));

如果你改为使用 strrpos($text, " ", 50),那么你将找到第 50 个字符和字符串末尾之间的最后一个空格,这可能不是你想要的结果。
dave at pixelmetrics dot com
5 年前
offset 的描述是错误的。以下是它的工作原理,以及支持示例。

Offset 影响搜索的起始点和结束点。方向始终是从右到左。(描述错误地指出当 offset 为正数时,PHP 从左到右搜索。)

以下是它的工作原理
当 offset 为正数时,PHP 从 haystack 的末尾到 offset 从右到左搜索。这会忽略 haystack 的左侧。

当 offset 为负数时,PHP 从右到左搜索,从末尾偏移 offset 个字节开始,到 haystack 的开头。这会忽略 haystack 的右侧。

示例 1
$foo = ‘aaaaaaaaaa’;
var_dump(strrpos($foo, 'a', 5));
结果:int(10)

示例 2
$foo = "aaaaaa67890";
var_dump(strrpos($foo, 'a', 5));
结果:int(5)

结论:当 offset 为正数时,PHP 从 haystack 的末尾从右到左搜索。

示例 3
$foo = "aaaaa567890";
var_dump(strrpos($foo, 'a', 5));
结果:bool(false)

结论:当 offset 为正数时,PHP 在 offset 处停止搜索。

示例 4
$foo = ‘aaaaaaaaaa’;
var_dump(strrpos($foo, 'a', -5));
结果:int(6)

结论:当 offset 为负数时,PHP 从右到左搜索,从末尾偏移 offset 个字节开始。

示例 5
$foo = "a234567890";
var_dump(strrpos($foo, 'a', -5));
结果:int(0)

结论:当 offset 为负数时,PHP 从右到左搜索,一直到 haystack 的开头。
david dot mann at djmann dot co dot uk
6 年前
十年过去了,Brian 的说明仍然很好地概述了 offset 的工作原理,但更短更简单的总结是

strrpos($x, $y, 50); // 1: 这告诉 strrpos() 何时停止,从 $x 的开头开始计数
strrpos($x, $y, -50); // 2: 这告诉 strrpos() 何时开始,从 $x 的末尾开始计数

或者换句话说,正数允许你搜索字符串的最右侧部分,而负数允许你搜索字符串的最左侧部分。

这两种变体都很有用,但选择错误的变体可能会导致一些非常混乱的结果!
Daniel Brinca
17 年前
这是一个简单的函数,用于查找 needle 在 haystack 中下一次出现的位,但反向搜索(lastIndexOf 类型函数)

// 反向搜索 haystack 中的 needle,并返回其位置
function rstrpos ($haystack, $needle, $offset){
$size = strlen ($haystack);
$pos = strpos (strrev($haystack), $needle, $size - $offset);

if ($pos === false)
return false;

return $size - $pos;
}

注意:支持将完整字符串作为 needle
anonymous
4 年前
关于 $offset 的工作原理有很多困惑,我觉得它其实很简单。

如果 $offset 为正数,则操作会忽略 haystack 的前 $offset 个字符。
如果 $offset 为负数,则操作会忽略 haystack 的最后 $offset-1 个字符(别问我为什么是 -1...)。

要本能地理解这一点,只需想象这些字符被替换为无效符号。这是一个例子

<?php
$hackstack
= '0123456789';

// 搜索整个序列 0123456789
var_dump(strrpos($hackstack, '0')); // int(0)
var_dump(strrpos($hackstack, '9')); // int(9)

// 只搜索 ##23456789
var_dump(strrpos($hackstack, '1', 2)); // bool(false)
var_dump(strrpos($hackstack, '2', 2)); // int(2)

// 只搜索 0123456###
var_dump(strrpos($hackstack, '6', -4)); // int(6)
var_dump(strrpos($hackstack, '7', -4)); // bool(false)

?>
stevewa
8 年前
我想在连字符之前找到一个前导空格

Crude Oil (Dec) 51.00-56.00

所以,我必须找到连字符的位置

然后从字符串的长度中减去该位置(使其成为负数)
然后向左走到字符串的开头,查找连字符之前的第一个空格

例如
$str_position_hyphen = strpos($line_new,"-",$str_position_spread);

$line_new_length = strlen($line_new);

$str_position_hyphen_from_end = $str_position_hyphen - $line_new_length;

echo "hyphen position from end = " . $str_position_hyphen_from_end . "<br />\n";


$str_position_space_before_hyphen = strrpos($line_new, " ", $str_position_hyphen_from_end);

echo "*** previous space= " . $str_position_space_before_hyphen . "<br />\n";

$line_new = substr_replace($line_new, ",", $str_position_space_before_hyphen, 1 );

echo $line_new . "<br /><br />\n";
islandispeace at hotmail dot com
9 年前
$offset 非常具有误导性,这是我的理解

function mystrrpos($haystack, $needle, $offset = 0) {
if ($offset == 0) {
return strrpos ($haystack, $needle);
} else {
return strrpos (substr($haystack, 0, $offset), $needle);
}
}
dmitry dot polushkin at gmail dot com
18 年前
返回文件名字符串扩展名,否则如果未找到扩展名则返回 false。
示例:filename_extension('some_file.mp3'); // mp3
速度是 pathinfo() 的两倍。
<?php
function filename_extension($filename) {
$pos = strrpos($filename, '.');
if(
$pos===false) {
return
false;
} else {
return
substr($filename, $pos+1);
}
}
?>
shimon at schoolportal dot co dot il
18 年前
在 php 4 中的 strrstr 函数中也没有 offset。
<?
// 作者:Shimon Doodkin
function chrrpos($haystack, $needle, $offset=false)
{
$needle=$needle[0];
$l=strlen($haystack);
if($l==0) return false;
if($offset===false) $offset=$l-1;
else
{
if($offset>$l) $offset=$l-1;
if($offset<0) return false;
}
for(;$offset>0;$offset--)
if($haystack[$offset]==$needle)
return $offset;
return false;
}
?>
gordon at kanazawa-gu dot ac dot jp
19 年前
此处建议的“查找字符串的最后一次出现”函数不允许使用起始偏移量,因此,这里有一个经过尝试和测试的函数,它确实允许使用起始偏移量

function my_strrpos($haystack, $needle, $offset=0) {
// 与 strrpos 相同,除了 $needle 可以是字符串
$strrpos = false;
if (is_string($haystack) && is_string($needle) && is_numeric($offset)) {
$strlen = strlen($haystack);
$strpos = strpos(strrev(substr($haystack, $offset)), strrev($needle));
if (is_numeric($strpos)) {
$strrpos = $strlen - $strpos - strlen($needle);
}
}
return $strrpos;
}
fab
19 年前
回复:hao2lian

此页面上有很多 strrpos() 的替代实现(不幸的是,它们有错误)(或称为 last_index_of)。这是一个对下面那个实现的略微修改,但它应该像一个真正的 strrpos() 一样工作,因为它在 haystack 中没有 needle 时返回 false。

<?php

function my_strrpos($haystack, $needle) {
$index = strpos(strrev($haystack), strrev($needle));
if(
$index === false) {
return
false;
}
$index = strlen($haystack) - strlen($needle) - $index;
return
$index;
}

?>
escii at hotmail dot com ( Brendan )
19 年前
当我发现 strrpos 的行为时,我立刻很生气(它不应该叫 charrpos 吗?)就是这样,所以我做了自己的实现来搜索字符串。

<?
function proper_strrpos($haystack,$needle){
while($ret = strrpos($haystack,$needle))
{
if(strncmp(substr($haystack,$ret,strlen($needle)),
$needle,strlen($needle)) == 0 )
return $ret;
$haystack = substr($haystack,0,$ret -1 );
}
return $ret;
}
?>
arlaud pierre
12 年前
这似乎与 PHP 4 版本的 PHP 5 偏移参数完全等效。

<?php
function strrpos_handmade($haystack, $needle, $offset = 0){

if(
$offset === 0) return strrpos($haystack, $needle);

$length = strlen($haystack);
$size = strlen($needle);

if(
$offset < 0) {
$virtual_cut = $length+$offset;
$haystack = substr($haystack, 0, $virtual_cut+$size);
$ret = strrpos($haystack, $needle);
return
$ret > $virtual_cut ? false : $ret;
} else {
$haystack = substr($haystack, $offset);
$ret = strrpos($haystack, $needle);
return
$ret === false ? $ret : $ret+$offset;
}

}
?>
su.noseelg@naes,仅向后
21 年前
也许只有我一个人为此烦恼,但当一段落中的最后一行是一个单独的单词时,我真的很讨厌。以下是一个解释我不喜欢的示例

The quick brown fox jumps over the lazy
dog。

所以这就是我编写此函数的原因。在任何包含多个空格(即超过两个单词)的段落中,它将用“&nbsp;”替换最后一个空格。

<?php
function no_orphans($TheParagraph) {
if (
substr_count($TheParagraph," ") > 1) {
$lastspace = strrpos($TheParagraph," ");
$TheParagraph = substr_replace($TheParagraph,"&nbsp;",$lastspace,1);
}
return
$TheParagraph;
}
?>

因此,它会将“The quick brown fox jumps over the lazy dog.” 更改为“The quick brown fox jumps over the lazy&nbsp;dog.”。这样,最后两个单词将始终保持在一起。
[email protected]
15 年前
我有一个执行反向 strpos 的简单方法,它可能有用。我拥有的此版本非常简单地处理偏移量
正偏移量从提供的字符串索引向后搜索。
负偏移量从字符串末尾的指定字符位置向后搜索。

以下是用此函数逐步向后遍历字符串实例的示例

<?php
function backwardStrpos($haystack, $needle, $offset = 0){
$length = strlen($haystack);
$offset = ($offset > 0)?($length - $offset):abs($offset);
$pos = strpos(strrev($haystack), strrev($needle), $offset);
return (
$pos === false)?false:( $length - $pos - strlen($needle) );
}

$pos = 0;
$count = 0;
echo
"Test1<br/>";
while((
$pos = backwardStrpos("012340567890", "0", $pos)) !== false){
echo
$pos."<br/>";
$pos--;
if(
$pos < 0){
echo
"Done<br/>";break;
}
}
echo
"---===---<br/>\nTest2<br/>";
echo
backwardStrpos("12341234", "1", 2)."<br/>";
echo
backwardStrpos("12341234", "1", -2);
?>

输出
Test1
11
5
0
Done
---===---
Test2
0
4

在 Test2 中,第一行从“12341234”中的第一个 3 开始检查,并向后运行直到找到一个 1(位于位置 0)

第二行从“12341234”中的第二个 2 开始检查,并向开头查找它找到的第一个 1(位于位置 4)。

此函数对 php4 有用,并且如果现有 strrpos 中的偏移参数与我一样令人困惑,它也很有用。
[email protected]
15 年前
我需要检查一个包含基于用户输入生成的文件夹名称的变量是否包含尾部斜杠。

这解决了问题

<?php
// 检测并移除尾部斜杠
$root_folder = ((strrpos($root_folder, '/') + 1) == strlen($root_folder)) ? substr($root_folder, 0, - 1) : $root_folder;
?>
FIE
21 年前
关于 lastIndexOf() 的注释和函数...
我发现它对我不起作用的唯一原因是干草堆被反转了,并且字符串没有被反转,因此它返回干草堆的长度而不是最后一个针的的位置...我将其重写如下

<?php
function strlpos($f_haystack,$f_needle) {
$rev_str = strrev($f_needle);
$rev_hay = strrev($f_haystack);
$hay_len = strlen($f_haystack);
$ned_pos = strpos($rev_hay,$rev_str);
$result = $hay_len - $ned_pos - strlen($rev_str);
return
$result;
}
?>

这个遵循 strpos 语法而不是 Java 的 lastIndexOf。
我不确定在那里分配所有这些变量是否需要更多资源,但如果你愿意,你可以将它们全部放在 return 中,我不在乎我的服务器是否崩溃;)。

~厄运的寂静之风呼啸!
[email protected]
17 年前
完整的 strpos() 功能,由本人提供。



<?php
function conforming_strrpos($haystack, $needle, $offset = 0)
{
# 为什么 strpos() 会这样做?无论如何...
if(!is_string($needle)) $needle = ord(intval($needle));
$haystack = strval($haystack);
# 参数
$hlen = strlen($haystack);
$nlen = strlen($needle);
# 得了吧,这也是一个特性
if($nlen == 0)
{
trigger_error(__FUNCTION__.'(): Empty delimiter.', E_USER_WARNING);
return
false;
}
$offset = intval($offset);
$hrev = strrev($haystack);
$nrev = strrev($needle);
# 搜索
$pos = strpos($hrev, $nrev, $offset);
if(
$pos === false) return false;
else return
$hlen - $nlen - $pos;
}
?>

请注意,$offset 从字符串的末尾开始计算。

另请注意,conforming_strrpos() 的执行速度比 strpos() 慢约五倍。仅供参考。
[email protected]
16 年前
<?php
$pos
= strlen(string $haystack) - strpos (strrev(string $haystack), strrev(string $needle)) - strlen(string $needle);
?>

如果在 $needle 中有多个字符,那么在 PHP 4 中,我们可以使用上述语句来查找字符串中子字符串最后一次出现的的位置,而不是使用 strrpos。因为在 PHP 4 中,strrpos 使用子字符串的第一个字符。

例如
<?php
$haystack
= "you you you you you";
$needle = "you";
$pos1 = strlen($haystack) - strpos (strrev($haystack), strrev($needle)) - strlen($needle);
echo
$pos1 . "<br>";
$pos2 strrpos($haystack, $needle);
echo
$pos2 . "<br>";
?>
[email protected]
21 年前
我正在寻找 Java 的 lastIndexOf() 的等价物。我找不到,所以我写了这个

<?php
/*
返回字符串中子字符串最后一次出现的位置的方法
字符串
*/
function last_index_of($sub_str,$instr) {
if(
strstr($instr,$sub_str)!="") {
return(
strlen($instr)-strpos(strrev($instr),$sub_str));
}
return(-
1);
}
?>

它返回您正在搜索的子字符串的数字索引,如果子字符串在字符串中不存在,则返回 -1。
[email protected]
17 年前
首先,对于我的英语,我表示歉意。
因此,我需要一个函数,它可以为我提供字符的前最后一个位置。
然后我对自己说,最好做一个可以提供“N”个最后一个位置的函数。

$return_context = "1173120681_0__0_0_Mijsoot_Thierry";

// 在这里我需要找到 = "Mijsoot_Thierry"

//echo $return_context."<br />";// -- DEBUG

function findPos($haystack,$needle,$position){
$pos = strrpos($haystack, $needle);
if($position>1){
$position --;
$haystack = substr($haystack, 0, $pos);
$pos = findPos($haystack,$needle,$position);
}else{
// echo $haystack."<br />"; // -- DEBUG
return $pos;
}
return $pos;
}

var_dump(findPos($return_context,"_",2)); // -- TEST
[email protected]
20 年前
搞什么鬼,我想我会在混合中添加另一个函数。它并不漂亮,但以下函数从您的起点倒数,并告诉您混合字符字符串的最后一次出现

<?php
function strrposmixed ($haystack, $needle, $start=0) {
// 如果未设置,则将 start 初始化为 str 的末尾
if($start == 0) {
$start = strlen($haystack);
}

// 从 $start 向后搜索
$currentStrPos=$start;
$lastFoundPos=false;

while(
$currentStrPos != 0) {
if(!(
strpos($haystack,$needle,$currentStrPos) === false)) {
$lastFoundPos=strpos($haystack,$needle,$currentStrPos);
break;
}
$currentStrPos--;
}

if(
$lastFoundPos === false) {
return
false;
} else {
return
$lastFoundPos;
}
}
?>
[email protected]
21 年前
我应该先看看这里,但我还是自己编写了 strrpos 的版本,它支持搜索整个字符串,而不是单个字符。这是一个递归函数。我还没有测试它是否比页面上的其他函数更有效或效率更低。我希望这能帮助到某些人!

<?php
//在 $haystack 中查找 $needle 的最后一次出现
function str_rpos($haystack, $needle, $start = 0){
$tempPos = strpos($haystack, $needle, $start);
if(
$tempPos === false){
if(
$start == 0){
// $needle 完全不在字符串中
return false;
}else{
// 未找到更多出现
return $start - strlen($needle);
}
}else{
// 查找下一次出现
return str_rpos($haystack, $needle, $tempPos + strlen($needle));
}
}
?>
[email protected]
18 年前
<?php
###################################################
#
# 描述:
# 此函数返回字符串的最后一次出现位置,
# 而不是像 strrpos 函数那样返回单个字符的最后一次出现位置。
# 它还支持从干草堆字符串中的哪个位置开始搜索的偏移量。
#
# 参数:
# $haystack(必需)-- 要搜索的字符串
# $needle(必需)-- 要查找的字符串
# $offset(可选)-- 开始搜索的偏移量
#
# 返回值:
# 成功时返回整数
# 完全找不到字符串时返回 false
#
###################################################

function strrpos_string($haystack, $needle, $offset = 0)
{
if(
trim($haystack) != "" && trim($needle) != "" && $offset <= strlen($haystack))
{
$last_pos = $offset;
$found = false;
while((
$curr_pos = strpos($haystack, $needle, $last_pos)) !== false)
{
$found = true;
$last_pos = $curr_pos + 1;
}
if(
$found)
{
return
$last_pos - 1;
}
else
{
return
false;
}
}
else
{
return
false;
}
}
?>
Christ Off
17 年前
截断字符串的函数
移除点和逗号
仅当找到字符时才添加 ...

function TruncateString($phrase, $longueurMax = 150) {
$phrase = substr(trim($phrase), 0, $longueurMax);
$pos = strrpos($phrase, " ");
$phrase = substr($phrase, 0, $pos);
if ((substr($phrase,-1,1) == ",") or (substr($phrase,-1,1) == ".")) {
$phrase = substr($phrase,0,-1);
}
if ($pos === false) {
$phrase = $phrase;
}
else {
$phrase = $phrase . "...";
}
return $phrase;
}
jonas at jonasbjork dot net
19 年前
我需要从路径中移除最后一个目录,并想出了这个解决方案

<?php

$path_dir
= "/my/sweet/home/";
$path_up = substr( $path_dir, 0, strrpos( $path_dir, '/', -2 ) )."/";
echo
$path_up;

?>

可能对某些人有用。
nexman at playoutloud dot net
20 年前
类似于 5.0 版本中 strrpos 的 4.x 版本的函数。
这将返回字符串中字符串的 *最后* 一次出现位置。

function strepos($haystack, $needle, $offset=0) {
$pos_rule = ($offset<0)?strlen($haystack)+($offset-1):$offset;
$last_pos = false; $first_run = true;
do {
$pos=strpos($haystack, $needle, (intval($last_pos)+(($first_run)?0:strlen($needle))));
if ($pos!==false && (($offset<0 && $pos <= $pos_rule)||$offset >= 0)) {
$last_pos = $pos;
} else { break; }
$first_run = false;
} while ($pos !== false);
if ($offset>0 && $last_pos<$pos_rule) { $last_pos = false; }
return $last_pos;
}

如果我的数学计算有误,请随时更正。
- 正偏移量将是允许的第一个字符的最小字符索引位置。
- 负偏移量将从总长度中减去,并且之前的那个位置将是正在搜索的第一个字符的最大索引。

返回 needle 最后一次出现的字符索引 (0+)。

* 布尔值 FALSE 将返回干草堆中没有匹配项,或超出偏移量指定的边界。
ZaraWebFX
21 年前
这可能是德里克提到的内容

<?
function cut_last_occurence($string,$cut_off) {
return strrev(substr(strstr(strrev($string), strrev($cut_off)),strlen($cut_off)));
}

// 例如:剪掉“limit”的最后一次出现
$str = "select delta_limit1, delta_limit2, delta_limit3 from table limit 1,7";
$search = " limit";
echo $str."\n";
echo cut_last_occurence($str,"limit");
?>
php NO at SPAMMERS willfris SREMMAPS dot ON nl
17 年前
<?php
/*******
** 即使在 php4 中,查找字符串最后一次出现的可能是最短的代码
*******/
function stringrpos($haystack,$needle,$offset=NULL)
{
return
strlen($haystack)
-
strpos( strrev($haystack) , strrev($needle) , $offset)
-
strlen($needle);
}
// @return -> 切割以提高可读性。
?>
genetically altered mastermind at gmail
19 年前
获取文件扩展名非常方便
$this->data['extension'] = substr($this->data['name'],strrpos($this->data['name'],'.')+1);
To Top