PHP Conference Japan 2024

strpos

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

strpos查找字符串中子字符串第一次出现的 位置

描述

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

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

参数

haystack

要搜索的字符串。

needle

要查找的字符串。

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

offset

如果指定,则搜索将从字符串开头开始计算的此数字字符开始。如果偏移量为负,则搜索将从字符串末尾开始计算的此数字字符开始。

返回值

返回 needle 相对于 haystack 字符串开头的存在位置(与 offset 无关)。还要注意,字符串位置从 0 开始,而不是 1

如果未找到 needle,则返回 false

警告

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

变更日志

版本 描述
8.0.0 needle 现在接受空字符串。
8.0.0 不再支持将 整数 作为 needle 传递。
7.3.0 整数 作为 needle 传递已被弃用。
7.1.0 已添加对负 offset 的支持。

示例

示例 #1 使用 ===

<?php
$mystring
= 'abc';
$findme = 'a';
$pos = strpos($mystring, $findme);

// 请注意我们使用了 ===。简单的 == 不会按预期工作
// 因为 'a' 的位置是第 0 个(第一个)字符。
if ($pos === false) {
echo
"在字符串 '$mystring' 中未找到字符串 '$findme'";
} else {
echo
"在字符串 '$mystring' 中找到字符串 '$findme'";
echo
" 并且存在于位置 $pos";
}
?>

示例 #2 使用 !==

<?php
$mystring
= 'abc';
$findme = 'a';
$pos = strpos($mystring, $findme);

// 也可以使用 !== 运算符。使用 != 不会按预期工作
// 因为 'a' 的位置是 0。语句 (0 != false) 计算结果为
// false。
if ($pos !== false) {
echo
"在字符串 '$mystring' 中找到字符串 '$findme'";
echo
" 并且存在于位置 $pos";
} else {
echo
"在字符串 '$mystring' 中未找到字符串 '$findme'";
}
?>

示例 #3 使用偏移量

<?php
// 我们可以搜索字符,忽略偏移量之前的任何内容
$newstring = 'abcdef abcdef';
$pos = strpos($newstring, 'a', 1); // $pos = 7,而不是 0
?>

注释

注意: 此函数是二进制安全的。

参见

  • stripos() - 查找字符串中不区分大小写的子字符串第一次出现的位置
  • str_contains() - 判断字符串是否包含给定子字符串
  • str_ends_with() - 检查字符串是否以给定子字符串结尾
  • str_starts_with() - 检查字符串是否以给定子字符串开头
  • strrpos() - 查找字符串中子字符串最后一次出现的位置
  • strripos() - 查找字符串中不区分大小写的子字符串最后一次出现的位置
  • strstr() - 查找字符串的第一次出现
  • strpbrk() - 在字符串中搜索一组字符中的任何一个
  • substr() - 返回字符串的一部分
  • preg_match() - 执行正则表达式匹配

添加注释

用户贡献的注释 35 个注释

建议重写粉红色警告框
16 年前
警告



由于 strpos 函数可能返回 FALSE(子字符串不存在)或 0(子字符串位于字符串开头),因此必须非常小心地使用严格和宽松的等价运算符。

要确定子字符串不存在,必须使用

=== FALSE

要确定子字符串存在(在任何位置,包括 0),可以使用以下任一方法:

!== FALSE(推荐)
> -1(注意:或大于任何负数)

要确定子字符串位于字符串开头,必须使用

=== 0

要确定子字符串位于除开头之外的任何位置,可以使用以下任一方法:

> 0(推荐)
!= 0(注意:但不能使用 !== 0,因为它也等价于 FALSE)
!= FALSE(不推荐,因为容易混淆)

还要注意,不能将 "" 的值与 strpos 的返回值进行比较。使用宽松的等价运算符(== 或 !=)将返回无法区分子字符串存在与位置的结果。使用严格的等价运算符(=== 或 !==)将始终返回 false。
fabio at naoimporta dot com
8 年前
了解使用不同编码的字符的字符串处理行为很有趣。

<?php
# 预期工作。没有重音符号
var_dump(strpos("Fabio", 'b'));
#int(2)

# "á" 字符占用两个位置
var_dump(strpos("Fábio", 'b')) ;
#int(3)

# 现在,将字符串 "Fábio" 编码为 utf8,我们得到了一些“意外”的输出。ASCII 表中没有的每个字母都将使用 4 个位置(字节)。起始点保持不变。
# 我们找不到字符,因为干草堆字符串现在已编码。
var_dump(strpos(utf8_encode("Fábio"), 'á'));
#bool(false)

# 要获得预期结果,我们需要对搜索字符串也进行编码
var_dump(strpos(utf8_encode("Fábio"), utf8_encode('á')));
#int(1)

# 并且,正如之前所说,"á" 占用 4 个位置(字节)
var_dump(strpos(utf8_encode("Fábio"), 'b'));
#int(5)
martijn at martijnfrazer dot nl
12 年前
这是一个我编写的使用 strpos 递归查找字符串所有出现的函数。

<?php
function strpos_recursive($haystack, $needle, $offset = 0, &$results = array()) {
$offset = strpos($haystack, $needle, $offset);
if(
$offset === false) {
return
$results;
} else {
$results[] = $offset;
return
strpos_recursive($haystack, $needle, ($offset + 1), $results);
}
}
?>

使用方法如下

<?php
$string
= 'This is some string';
$search = 'a';
$found = strpos_recursive($string, $search);

if(
$found) {
foreach(
$found as $pos) {
echo
'在字符串 "'.$string.'" 中找到 "'.$search.'",位置为 <b>'.$pos.'</b><br />';
}
} else {
echo
'"'.$search.'" 未在 "'.$string.'" 中找到';
}
?>
mtroy dot student at gmail dot com
12 年前
当您想知道子字符串出现的次数时,可以使用 "substr_count"。
但是,检索它们的位置会更难。
因此,您可以从最后一次出现开始

function strpos_r($haystack, $needle)
{
if(strlen($needle) > strlen($haystack))
trigger_error(sprintf("%s: 参数 2 的长度必须小于或等于参数 1", __FUNCTION__), E_USER_WARNING);

$seeks = array();
while($seek = strrpos($haystack, $needle))
{
array_push($seeks, $seek);
$haystack = substr($haystack, 0, $seek);
}
return $seeks;
}

它将返回字符串中子字符串所有出现的数组

示例

$test = "this is a test for testing a test function... blah blah";
var_dump(strpos_r($test, "test"));

// 输出

array(3) {
[0]=>
int(29)
[1]=>
int(19)
[2]=>
int(10)
}

Paul-antoine
Malézieux.
m.m.j.kronenburg

8 年前
<?php

/**
* 查找字符串中一个或多个子字符串首次出现的位置。
*
* 此函数类似于函数 strpos(),但它允许同时搜索多个子字符串。
*
* @param string $haystack 要搜索的字符串。
* @param mixed $needles 包含子字符串的数组或包含子字符串的字符串。
* @param integer $offset 如果指定,则搜索将从字符串开头算起的此数字个字符开始。
* @param boolean $last 如果为 TRUE,则返回其中一个子字符串最远的位置。
* 如果为 FALSE,则返回其中一个子字符串最靠近开始位置的位置。
**/
function mstrpos($haystack, $needles, $offset = 0, $last = false)
{
if(!
is_array($needles)) { $needles = array($needles); }
$found = false;
foreach(
$needles as $needle)
{
$position = strpos($haystack, (string)$needle, $offset);
if(
$position === false) { continue; }
$exp = $last ? ($found === false || $position > $found) :
(
$found === false || $position < $found);
if(
$exp) { $found = $position; }
}
return
$found;
}

/**
* 查找字符串中子字符串首次(部分)出现的位置。
*
* 此函数类似于函数 strpos(),但当子字符串部分位于字符串末尾时,它将返回一个位置。
*
* @param string $haystack 要搜索的字符串。
* @param mixed $needle 要搜索的子字符串。
* @param integer $offset 如果指定,则搜索将从字符串开头算起的此数字个字符开始。
**/
function pstrpos($haystack, $needle, $offset = 0)
{
$position = strpos($haystack, $needle, $offset);
if(
$position !== false) { return $position; }

for(
$i = strlen($needle); $i > 0; $i--)
{
if(
substr($needle, 0, $i) == substr($haystack, -$i))
{ return
strlen($haystack) - $i; }
}
return
false;
}

/**
* 查找字符串中一个或多个子字符串首次(部分)出现的位置。
*
* 此函数类似于函数 strpos(),但它允许同时搜索多个子字符串,并且当其中一个子字符串部分位于字符串末尾时,它将返回一个位置。
*
* @param string $haystack 要搜索的字符串。
* @param mixed $needles 包含子字符串的数组或包含子字符串的字符串。
* @param integer $offset 如果指定,则搜索将从字符串开头算起的此数字个字符开始。
* @param boolean $last 如果为 TRUE,则返回其中一个子字符串最远的位置。
* 如果为 FALSE,则返回其中一个子字符串最靠近开始位置的位置。
**/
function mpstrpos($haystack, $needles, $offset = 0, $last = false)
{
if(!
is_array($needles)) { $needles = array($needles); }
$found = false;
foreach(
$needles as $needle)
{
$position = pstrpos($haystack, (string)$needle, $offset);
if(
$position === false) { continue; }
$exp = $last ? ($found === false || $position > $found) :
(
$found === false || $position < $found);
if(
$exp) { $found = $position; }
}
return
$found;
}

?>
greg at spotx dot net
7 年前
警告
这并非 Unicode 安全的。

strpos($word,'?') 在 e?ez-> 1
strpos($word,'?') 在 è?ent-> 2
rjeggens at ijskoud dot org
12 年前
我花了一个小时才注意到 strpos 仅将 FALSE 作为布尔值返回,从不返回 TRUE。这意味着

strpos() !== false



strpos() === true

是不同的,因为后者永远不会为真。在我发现这一点后,文档中的警告就更有意义了。
jexy dot ru at gmail dot com
7 年前
文档缺少如果 needle 为空字符串 ('') 则会发出 WARNING 的说明。

如果 haystack 为空,则它只返回 false

例如

<?php
var_dump
(strpos('foo', ''));

var_dump(strpos('', 'foo'));

var_dump(strpos('', ''));
?>

将输出

Warning: strpos(): Empty needle in /in/lADCh on line 3
bool(false)

bool(false)

Warning: strpos(): Empty needle in /in/lADCh on line 7
bool(false)

还要注意,警告文本可能因 PHP 版本而异,请参见 https://3v4l.org/lADCh
ilaymyhat-rem0ve at yahoo dot com
16 年前
这可能很有用。

<?php
class String{

//在任意位置查找 $haystack 中的 $needle
public static function contains(&$haystack, &$needle, &$offset)
{
$result = strpos($haystack, $needle, $offset);
return
$result !== FALSE;
}

//直观的实现..如果未找到则返回 -1。
public static function strpos(&$haystack, &$needle, &$offset)
{
$result = strpos($haystack, $needle, $offset);
if (
$result === FALSE )
{
return -
1;
}
return
$result;
}

}
//String
?>

eef dot vreeland at gmail dot com
7 年前
为了防止其他人盯着这段文字看,请注意“返回值”部分的措辞含糊不清。

假设你有一个字符串 $myString,包含 50 个 'a',除了第 3 位和第 43 位,它们包含 'b'。
并且目前,先忘记计数是从 0 开始的。

strpos($myString, 'b', 40) 返回 43,很好。

现在来看这段文字:“返回针存在于干草堆字符串开头的位置(与偏移量无关)”。

所以,我指定的偏移量实际上并不重要;我将获得第一个出现的真实位置作为返回值,也就是 3 吗?

… 不…

“与偏移量无关”的意思是,你将获得真实位置,因此,不是相对于你的起始点(偏移量)。

从 strpos() 的答案中减去你的偏移量,然后你就可以得到相对于你偏移量的位置。
user at nomail dot com
17 年前
当扫描一个大型字符串以查找“标签”之间的所有出现时,这更有用。

<?php
function getStrsBetween($s,$s1,$s2=false,$offset=0) {
/*====================================================================
用于扫描字符串以查找封装在一对标签中的项目的函数

getStrsBetween(字符串, 标签1, <标签2>, <偏移量>

如果未指定第二个标签,则匹配相同的标签

返回一个数组,其中索引为封装的文本,该文本依次
是一个子数组,包含每个项目的位置。

注意:
strpos($needle,$haystack,$offset)
substr($string,$start,$length)

====================================================================*/

if( $s2 === false ) { $s2 = $s1; }
$result = array();
$L1 = strlen($s1);
$L2 = strlen($s2);

if(
$L1==0 || $L2==0 ) {
return
false;
}

do {
$pos1 = strpos($s,$s1,$offset);

if(
$pos1 !== false ) {
$pos1 += $L1;

$pos2 = strpos($s,$s2,$pos1);

if(
$pos2 !== false ) {
$key_len = $pos2 - $pos1;

$this_key = substr($s,$pos1,$key_len);

if( !
array_key_exists($this_key,$result) ) {
$result[$this_key] = array();
}

$result[$this_key][] = $pos1;

$offset = $pos2 + $L2;
} else {
$pos1 = false;
}
}
} while(
$pos1 !== false );

return
$result;
}
?>
akarmenia at gmail dot com
13 年前
我版本的 strpos,其中 needle 为数组。也允许使用字符串或数组中的数组。

<?php
function strpos_array($haystack, $needles) {
if (
is_array($needles) ) {
foreach (
$needles as $str) {
if (
is_array($str) ) {
$pos = strpos_array($haystack, $str);
} else {
$pos = strpos($haystack, $str);
}
if (
$pos !== FALSE) {
return
$pos;
}
}
} else {
return
strpos($haystack, $needles);
}
}

// 测试
echo strpos_array('This is a test', array('test', 'drive')); // 输出为 10

?>
marvin_elia at web dot de
6 年前
查找字符串第 n 次出现的的位置

function strpos_occurrence(string $string, string $needle, int $occurrence, int $offset = null) {
if((0 < $occurrence) && ($length = strlen($needle))) {
do {
} while ((false !== $offset = strpos($string, $needle, $offset)) && --$occurrence && ($offset += $length));
return $offset;
}
return false;
}
digitalpbk [at] gmail.com
15 年前
如果偏移量不在字符串长度的 0 到长度之间,此函数会引发警告

警告:strpos(): 偏移量未包含在字符串中,位于 %s 的第 %d 行
ohcc at 163 dot com
10 年前
当 $haystack 或 $needle 参数为整数时,请小心。
如果不确定其类型,应将其转换为字符串。
<?php
var_dump
(strpos(12345,1));//false
var_dump(strpos(12345,'1'));//0
var_dump(strpos('12345',1));//false
var_dump(strpos('12345','1'));//0
$a = 12345;
$b = 1;
var_dump(strpos(strval($a),strval($b)));//0
var_dump(strpos((string)$a,(string)$b));//0
?>
lairdshaw at yahoo dot com dot au
9 年前
<?php
/*
* strpos 的变体,接受一个 $needles 数组 - 或只是一个字符串,
* 因此它可以用作标准 strpos 的直接替换,
* 在这种情况下,它只是围绕 strpos 和 stripos 进行包装,以避免
* 降低性能。
*
* "strposm" 中的 "m" 表示它接受 *多*个 needle。
*
* 查找 *所有* needle 的最早匹配项。返回此匹配项的位置
* 或如果未找到则返回 false,就像标准 strpos 一样。还可以选择
* 通过 $match 返回匹配的 needle 作为字符串(默认情况下)或索引
* 到 $needles 中匹配的 needle 的索引(如果设置了 STRPOSM_MATCH_AS_INDEX 标志)。
*
* 可以通过 STRPOSM_CI 标志指定不区分大小写的搜索。
* 请注意,对于不区分大小写的搜索,如果未设置 STRPOSM_MATCH_AS_INDEX,
* 则 $match 将使用 haystack 的大小写,而不是 needle 的大小写,
* 除非还设置了 STRPOSM_NC 标志。
*
* 可以使用按位或运算符组合标志,
* 例如 $flags = STRPOSM_CI|STRPOSM_NC
*/
define('STRPOSM_CI' , 1); // CI => "不区分大小写"。
define('STRPOSM_NC' , 2); // NC => "needle 的大小写"。
define('STRPOSM_MATCH_AS_INDEX', 4);
function
strposm($haystack, $needles, $offset = 0, &$match = null, $flags = 0) {
// 在 $needles 不是数组的特殊情况下,只需包装
// strpos 和 stripos 以提高性能。
if (!is_array($needles)) {
$func = $flags & STRPOSM_CI ? 'stripos' : 'strpos';
$pos = $func($haystack, $needles, $offset);
if (
$pos !== false) {
$match = (($flags & STRPOSM_MATCH_AS_INDEX)
?
0
: (($flags & STRPOSM_NC)
?
$needles
: substr($haystack, $pos, strlen($needles))
)
);
return
$pos;
} else goto
strposm_no_match;
}

// $needles 是一个数组。适当地继续,首先通过...
// ...转义 needle 中的正则表达式元字符。
$needles_esc = array_map('preg_quote', $needles);
// 如果设置了 "needle 的大小写" 或 "匹配作为索引" 标志,
// 则通过将每个转义的 needle 包含在
// 括号中来为其创建子匹配。我们稍后使用这些来查找匹配
// needle 的索引。
if (($flags & STRPOSM_NC) || ($flags & STRPOSM_MATCH_AS_INDEX)) {
$needles_esc = array_map(
function(
$needle) {return '('.$needle.')';},
$needles_esc
);
}
// 创建正则表达式模式以搜索所有 needle。
$pattern = '('.implode('|', $needles_esc).')';
// 如果设置了 "不区分大小写" 标志,则使用 "i" 修改正则表达式,
// 意思是匹配 "不区分大小写"。
if ($flags & STRPOSM_CI) $pattern .= 'i';
// 查找第一个匹配项,包括其偏移量。
if (preg_match($pattern, $haystack, $matches, PREG_OFFSET_CAPTURE, $offset)) {
// 从匹配数组中提取第一个条目,即整体匹配。
$found = array_shift($matches);
// 如果我们需要匹配 needle 的索引,则...
if (($flags & STRPOSM_NC) || ($flags & STRPOSM_MATCH_AS_INDEX)) {
// ...查找与我们刚刚提取的整体匹配相同的子匹配的索引。
// 因为子匹配与 needle 的顺序相同,
// 这也是 $needles 中匹配
// needle 的索引。
$index = array_search($found, $matches);
}
// 如果设置了 "匹配作为索引" 标志,则在 $match 中返回
// 匹配的 needle 的索引,否则...
$match = (($flags & STRPOSM_MATCH_AS_INDEX)
?
$index
// ...如果设置了 "needle 的大小写" 标志,则使用先前确定的索引索引到
// $needles 中,以在 $match 中返回
// 匹配的 needle 的 needle 的大小写,否则...
: (($flags & STRPOSM_NC)
?
$needles[$index]
// ...默认情况下,在 $match 中返回 haystack 的大小写的匹配 needle。
: $found[0]
)
);
// 返回捕获的偏移量。
return $found[1];
}

strposm_no_match:
// 没有匹配。设置适当的返回值。
$match = ($flags & STRPOSM_MATCH_AS_INDEX) ? false : null;
return
false;
}
?>
teddanzig at yahoo dot com
15 年前
例程,如果 strpos 没有匹配则返回 -1

<?php
//instr 函数模仿 vb instr 函数
function InStr($haystack, $needle)
{
$pos=strpos($haystack, $needle);
if (
$pos !== false)
{
return
$pos;
}
else
{
return -
1;
}
}
?>
usulaco at gmail dot com
14 年前
将两个其他字符串之间的字符串解析到数组中。

<?php
function g($string,$start,$end){
preg_match_all('/' . preg_quote($start, '/') . '(.*?)'. preg_quote($end, '/').'/i', $string, $m);
$out = array();

foreach(
$m[1] as $key => $value){
$type = explode('::',$value);
if(
sizeof($type)>1){
if(!
is_array($out[$type[0]]))
$out[$type[0]] = array();
$out[$type[0]][] = $type[1];
} else {
$out[] = $value;
}
}
return
$out;
}
print_r(g('示例文本,[/要提取的文本/]示例文本的其余部分[/WEB::http://google.com/] 等等。','[/','/]'));
?>

结果
数组
(
[0] => 要提取的文本
[WEB] => 数组
(
[0] => http://google.com
)

)

可以帮助自定义解析 :)
Jean
5年前
当一个值可以是“未知”类型时,我发现这种转换技巧很有用,并且比正式的强制转换更易读(适用于 php7.3+)

<?php
$time
= time();
$string = '这是一个测试: ' . $time;
echo (
strpos($string, $time) !== false ? '找到' : '未找到');
echo (
strpos($string, "$time") !== false ? '找到' : '未找到');
?>
bishop
20年前
像这样的代码
<?php
if (strpos('这是一个测试', 'is') !== false) {
echo
"找到它了";
}
?>

变得重复,不是很有自解释性,而且大多数人无论如何都会处理错误。让你的生活更轻松

<?php
function str_contains($haystack, $needle, $ignoreCase = false) {
if (
$ignoreCase) {
$haystack = strtolower($haystack);
$needle = strtolower($needle);
}
$needlePos = strpos($haystack, $needle);
return (
$needlePos === false ? false : ($needlePos+1));
}
?>

然后,你可以这样做
<?php
// 最简单的用法
if (str_contains('这是一个测试', 'is')) {
echo
"找到它了";
}

// 当你也需要位置以及是否存在时
$needlePos = str_contains('这是一个测试', 'is');
if (
$needlePos) {
echo
'在位置 ' . ($needlePos-1);
}

// 你也可以忽略大小写
$needlePos = str_contains('这是一个测试', 'IS', true);
if (
$needlePos) {
echo
'在位置 ' . ($needlePos-1);
}
?>
Achintya
15 年前
我创建了一个函数来查找特定针的第一次出现,该针不包含在引号(单引号或双引号)中。适用于简单的嵌套(不允许反斜杠嵌套)。

<?php
function strposq($haystack, $needle, $offset = 0){
$len = strlen($haystack);
$charlen = strlen($needle);
$flag1 = false;
$flag2 = false;
for(
$i = $offset; $i < $len; $i++){
if(
substr($haystack, $i, 1) == "'"){
$flag1 = !$flag1 && !$flag2 ? true : false;
}
if(
substr($haystack, $i, 1) == '"'){
$flag2 = !$flag1 && !$flag2 ? true : false;
}
if(
substr($haystack, $i, $charlen) == $needle && !$flag1 && !$flag2){
return
$i;
}
}
return
false;
}

echo
strposq("he'llo'character;\"'som\"e;crap", ";"); //16
?>
qrworld.net
10 年前
我在这篇文章中找到了一个函数 http://softontherocks.blogspot.com/2014/11/buscar-multiples-textos-en-un-texto-con.html
它实现了两种方式的搜索,区分大小写或不区分大小写,具体取决于输入参数。

函数是

function getMultiPos($haystack, $needles, $sensitive=true, $offset=0){
foreach($needles as $needle) {
$result[$needle] = ($sensitive) ? strpos($haystack, $needle, $offset) : stripos($haystack, $needle, $offset);
}
return $result;
}

这对我很实用。
匿名
11年前
防止此函数返回 0 的最直接方法是

strpos('x'.$haystack, $needle, 1)

“x”只是一个垃圾字符,它仅仅是为了将所有内容移动 1 个位置。
数字 1 用于确保在搜索中忽略此“x”。
这样,如果 $haystack 以 $needle 开头,则函数返回 1(而不是 0)。
Tim
16 年前
如果要查找干草堆中针的所有出现次数,可以使用此函数 strposall($haystack,$needle);。它将返回一个包含所有 strpos 的数组。

<?php
/**
* strposall
*
* 查找字符串中所有目标字符串出现的起始位置
*
* @param string $haystack 要查找的字符串
* @param string $needle 目标字符串
* @return array 或 false
*/
function strposall($haystack,$needle){

$s=0;
$i=0;

while (
is_integer($i)){

$i = strpos($haystack,$needle,$s);

if (
is_integer($i)) {
$aStrPos[] = $i;
$s = $i+strlen($needle);
}
}
if (isset(
$aStrPos)) {
return
$aStrPos;
}
else {
return
false;
}
}
?>
ah dot d at hotmail dot com
15 年前
修改 strpos 函数,使其返回目标字符串在字符串中所有出现位置的数组

<?php
function strallpos($haystack,$needle,$offset = 0){
$result = array();
for(
$i = $offset; $i<strlen($haystack); $i++){
$pos = strpos($haystack,$needle,$i);
if(
$pos !== FALSE){
$offset = $pos;
if(
$offset >= $i){
$i = $offset;
$result[] = $offset;
}
}
}
return
$result;
}
?>

示例:

<?php
$haystack
= "ASD 正在试图走出 ASDs 的立方体,但其他 ASDs 告诉他,他的行为会毁掉 ASDs 的世界";

$needle = "ASD";

print_r(strallpos($haystack,$needle));

//从指定位置开始获取所有位置

print_r(strallpos($haystack,$needle,34));
?>
Lhenry
7 年前
注意 strpos( "8 june 1970" , 1970 ) 返回 FALSE。

在目标字符串周围添加引号
spinicrus at gmail dot com
18 年前
如果你想获取子字符串相对于字符串子字符串的位置,但以相反的方式

<?php

function strpos_reverse_way($string,$charToFind,$relativeChar) {
//
$relativePos = strpos($string,$relativeChar);
$searchPos = $relativePos;
$searchChar = '';
//
while ($searchChar != $charToFind) {
$newPos = $searchPos-1;
$searchChar = substr($string,$newPos,strlen($charToFind));
$searchPos = $newPos;
}
//
if (!empty($searchChar)) {
//
return $searchPos;
return
TRUE;
}
else {
return
FALSE;
}
//
}

?>
sunmacet at gmail dot com
4 年前
检查子字符串是否存在。

如果位置不为 false,则检查是否令人困惑

if ( strpos ( $haystack , $needle ) !== FALSE )

逻辑检查是否存在位置

if ( is_int ( strpos ( $haystack , $needle ) ) )
gjh42 - simonokewode at hotmail dot com
13 年前
一对函数,用于将字符串中每个第 n 个出现的字符串替换为另一个字符串,从干草堆中的任意位置开始。第一个函数作用于字符串,第二个函数作用于字符串的一级数组,将其视为单个字符串进行替换(任何跨越两个数组元素的搜索字符串都会被忽略)。

可用于格式化动态生成的 HTML 输出,而无需修改原始生成器:例如,为浮动列表中的每三个项目添加一个 newLine 类标签,从第四个项目开始。

<?php
/* 字符串间隔替换,作者 Glenn Herbert (gjh42) 2010-12-17
*/

//(基本定位器由其他人编写 - 姓名未知)
//strnposr() - 查找字符串中第 n 个目标字符串的位置。
function strnposr($haystack, $needle, $occurrence, $pos = 0) {
return (
$occurrence<2)?strpos($haystack, $needle, $pos):strnposr($haystack,$needle,$occurrence-1,strpos($haystack, $needle, $pos) + 1);
}

//gjh42
//从任意位置开始,替换每个第 n 个出现的 $needle 为 $repl。
function str_replace_int($needle, $repl, $haystack, $interval, $first=1, $pos=0) {
if (
$pos >= strlen($haystack) or substr_count($haystack, $needle, $pos) < $first) return $haystack;
$firstpos = strnposr($haystack, $needle, $first, $pos);
$nl = strlen($needle);
$qty = floor(substr_count($haystack, $needle, $firstpos + 1)/$interval);
do {
//以逆序进行
$nextpos = strnposr($haystack, $needle, ($qty * $interval) + 1, $firstpos);
$qty--;
$haystack = substr_replace($haystack, $repl, $nextpos, $nl);
} while (
$nextpos > $firstpos);
return
$haystack;
}
//$needle = 要查找的字符串
//$repl = 用于替换 $needle 的字符串
//$haystack = 要进行替换操作的字符串
//$interval = 循环中 $needle 的数量
//$first=1 = 要替换的 $needle 的第一个出现位置(默认为第一个)
//$pos=0 = 在 $haystack 字符串中开始查找的位置(默认为第一个)

//从任意位置开始,在单层数组中替换每个第 n 个出现的 $needle 为 $repl。
function arr_replace_int($needle, $repl, $arr, $interval, $first=1, $pos=0, $glue='|+|') {
if (!
is_array($arr)) return $arr;
foreach(
$arr as $key=>$value){
if (
is_array($arr[$key])) return $arr;
}
$haystack = implode($glue, $arr);
$haystack = str_replace_int($needle, $repl, $haystack, $interval, $first, $pos);
$tarr = explode($glue, $haystack);
$i = 0;
foreach(
$arr as $key=>$value){
$arr[$key] = $tarr[$i];
$i++;
}
return
$arr;
}
?>
如果 $arr 不是数组,或不是多维数组,则返回其本身。
[email protected]
14 年前
<?php
$my_array
= array ('100,101', '200,201', '300,301');
$check_me_in = array ('100','200','300','400');
foreach (
$check_me_in as $value_cmi){
$is_in=FALSE; #假设 $check_me_in 不在 $my_array 中
foreach ($my_array as $value_my){
$pos = strpos($value_my, $value_cmi);
if (
$pos===0)
$pos++;
if (
$pos==TRUE){
$is_in=TRUE;
$value_my2=$value_my;
}
}
if (
$is_in) echo "ID $value_cmi 在 \$check_me_in 中,我在值 '$value_my2' 中找到了\n";
}
?>

以上示例将输出
ID 100 在 $check_me_in 中,我在值 '100,101' 中找到了
ID 200 在 $check_me_in 中,我在值 '200,201' 中找到了
ID 300 在 $check_me_in 中,我在值 '300,301' 中找到了
[email protected]
15 年前
此函数查找从偏移量开始的第 n 个字符的位置。

<?php
function nth_position($str, $letter, $n, $offset = 0){
$str_arr = str_split($str);
$letter_size = array_count_values(str_split(substr($str, $offset)));
if( !isset(
$letter_size[$letter])){
trigger_error('字符 "' . $letter . '" 在 ' . $str . ' 的 ' . $offset . ' 之后不存在。位置', E_USER_WARNING);
return
false;
} else if(
$letter_size[$letter] < $n) {
trigger_error('字符 "' . $letter . '" 在 ' . $str . ' 的 ' . $offset . ' 之后没有出现 ' . $n .' 次。位置', E_USER_WARNING);
return
false;
}
for(
$i = $offset, $x = 0, $count = (count($str_arr) - $offset); $i < $count, $x != $n; $i++){
if(
$str_arr[$i] == $letter){
$x++;
}
}
return
$i - 1;
}

echo
nth_position('foobarbaz', 'a', 2); //7
echo nth_position('foobarbaz', 'b', 1, 4); //6
?>
[email protected]
4 年前
注意以下 PHP 7.3 中的代码示例
<?php
$str
= "17,25";

if(
FALSE !== strpos($str, 25)){
echo
"25 is inside of str";
} else {
echo
"25 is NOT inside of str";
}
?>

将会输出 "25 is NOT inside of str" 并且会抛出一个弃用消息,表示将来非字符串的搜索值会被解释为字符串。

这让我有点头疼,因为我正在检查的值来自数据库,是一个整数。
philip
20年前
很多人都在寻找不存在于PHP中的 in_string 函数,所以,这是我能想到的最有效的 in_string() 函数形式(在PHP 4/5中都适用)
<?php
function in_string($needle, $haystack, $insensitive = false) {
if (
$insensitive) {
return
false !== stristr($haystack, $needle);
} else {
return
false !== strpos($haystack, $needle);
}
}
?>
Lurvik
10 年前
不知道是否已经发布过这个,但如果我发布了,这是一个改进。

此函数将检查字符串是否包含某个搜索值。它_将_适用于数组和多维数组(我尝试了一个>16维数组,没有问题)。

<?php
function str_contains($haystack, $needles)
{
//如果搜索值是数组
if(is_array($needles))
{
//遍历所有元素
foreach($needles as $needle)
{
//如果搜索值也是数组(即搜索值是一个多维数组)
if(is_array($needle))
{
//再次调用此函数
if(str_contains($haystack, $needle))
{
//将跳出循环和函数。
return true;
}

return
false;
}

//当搜索值不是数组时:
//检查目标字符串是否包含搜索值,将忽略大小写并仅检查完整单词
elseif(preg_match("/\b$needle\b/i", $haystack) !== 0)
{
return
true;
}
}
}
//如果$needles不是数组...
else
{
if(
preg_match("/\b$needles\b/i", $haystack) !== 0)
{
return
true;
}
}

return
false;
}
?>
amolocaleb at gmail dot com
6 年前
请注意,strpos() 是区分大小写的,因此在执行不区分大小写的搜索时,请使用 stripos() 代替。如果后者不可用,请先将字符串转换为小写,否则您可能会遇到这种情况。
<?php
//假设我们正在匹配 URL 路由,并根据路由调用访问控制中间件

$registered_route = '/admin' ;
//现在假设我们希望在访问管理员路由之前调用授权中间件
if(strpos($path->url(),$registered_route) === 0){
$middleware->call('Auth','login');
}
?>
授权中间件如下
<?php
class Auth{

function
login(){
if(!
loggedIn()){
return
redirect("path/to/login.php");
}
return
true;
}
}

//现在假设:
$user_url = '/admin';
//这将进入 Auth 中间件进行检查并相应地重定向

//但是:
$user_url = '/Admin';
//这将使 strpos 函数返回 false,因为 admin 中的 'A' 是大写,用户将直接进入管理员仪表盘,而不管身份验证和授权
?>
简单的修复方法
<?php
//从 PHP 5 开始使用 stripos()
if(stripos($path->url(),$registered_route) === 0){
$middleware->call('Auth','login');
}
//对于使用 PHP 4 的用户
if(stripos(strtolower($path->url()),$registered_route) === 0){
$middleware->call('Auth','login');
}
//确保 $registered_route 也是小写。或者只需升级到 PHP 5>
To Top