PHP 查找字符串中所有出现的子字符串
Posted
技术标签:
【中文标题】PHP 查找字符串中所有出现的子字符串【英文标题】:PHP Find all occurrences of a substring in a string 【发布时间】:2013-03-22 04:06:29 【问题描述】:我需要解析一个 html 文档并在其中找到所有出现的字符串 asdf
。
我目前已将 HTML 加载到字符串变量中。我只想要字符位置,这样我就可以遍历列表以在字符串之后返回一些数据。
strpos
函数只返回 first 出现。 全部返回怎么样?
【问题讨论】:
【参考方案1】:不使用正则表达式,这样的东西应该可以返回字符串位置:
$html = "dddasdfdddasdffff";
$needle = "asdf";
$lastPos = 0;
$positions = array();
while (($lastPos = strpos($html, $needle, $lastPos))!== false)
$positions[] = $lastPos;
$lastPos = $lastPos + strlen($needle);
// Displays 3 and 10
foreach ($positions as $value)
echo $value ."<br />";
【讨论】:
请小心在if
语句中使用赋值。在这种情况下,您的 while
循环不适用于位置 0
。我已经更新了你的答案。
很好的修复,但对于那些需要查找特殊字符(é、ë、...)的人,请将 strpos 替换为 mb_strpos,否则将无法正常工作
所有将重用此代码的人都要小心,因为您的指针可能类似于“dd”,在这种情况下,$lastPos 应该只在 while 循环内增加 1。【参考方案2】:
您可以重复调用strpos
函数,直到找不到匹配项。您必须指定偏移参数。
注意:在以下示例中,搜索从 下一个 字符开始,而不是从上一个匹配项的结尾开始。根据这个函数,aaaa
包含 三个 出现的子字符串 aa
,而不是两个。
function strpos_all($haystack, $needle)
$offset = 0;
$allpos = array();
while (($pos = strpos($haystack, $needle, $offset)) !== FALSE)
$offset = $pos + 1;
$allpos[] = $pos;
return $allpos;
print_r(strpos_all("aaa bbb aaa bbb aaa bbb", "aa"));
输出:
Array
(
[0] => 0
[1] => 1
[2] => 8
[3] => 9
[4] => 16
[5] => 17
)
【讨论】:
【参考方案3】:最好使用substr_count
。查看php.net
【讨论】:
这只会给你计数,而不是他们提出的问题的位置 "这个函数不计算重叠的子串。"对于字符串 'abababa',当您查看 'aba' 时,它只会计算 2 次而不是 3 次【参考方案4】:function getocurence($chaine,$rechercher)
$lastPos = 0;
$positions = array();
while (($lastPos = strpos($chaine, $rechercher, $lastPos))!== false)
$positions[] = $lastPos;
$lastPos = $lastPos + strlen($rechercher);
return $positions;
【讨论】:
纯代码答案在 *** 上的价值很低,因为它们对 OP 和未来的读者的教育作用很小。请编辑您的答案,以教育成千上万的未来 SO 读者和 OP。【参考方案5】:使用preg_match_all
查找所有个事件。
preg_match_all('/(\$[a-z]+)/i', $str, $matches);
更多参考请查看this link。
【讨论】:
他正在寻找字符串位置,而不仅仅是匹配项。他还希望匹配“asdf”,而不是 [a-z]...【参考方案6】:这可以使用 strpos() 函数来完成。下面的代码是使用 for 循环实现的。这段代码非常简单而且非常直接。
<?php
$str_test = "Hello World! welcome to php";
$count = 0;
$find = "o";
$positions = array();
for($i = 0; $i<strlen($str_test); $i++)
$pos = strpos($str_test, $find, $count);
if($pos == $count)
$positions[] = $pos;
$count++;
foreach ($positions as $value)
echo '<br/>' . $value . "<br />";
?>
【讨论】:
【参考方案7】:Salman A 有一个很好的答案,但请记住让您的代码具有多字节安全性。要使用 UTF-8 获得正确的位置,请使用 mb_strpos 而不是 strpos:
function strpos_all($haystack, $needle)
$offset = 0;
$allpos = array();
while (($pos = mb_strpos($haystack, $needle, $offset)) !== FALSE)
$offset = $pos + 1;
$allpos[] = $pos;
return $allpos;
print_r(strpos_all("aaa bbb aaa bbb aaa bbb", "aa"));
【讨论】:
【参考方案8】:简单的strpos_all()函数。
function strpos_all($haystack, $needle_regex)
preg_match_all('/' . $needle_regex . '/', $haystack, $matches, PREG_OFFSET_CAPTURE);
return array_map(function ($v)
return $v[1];
, $matches[0]);
用法: 像针一样简单的绳子。
$html = "dddasdfdddasdffff";
$needle = "asdf";
$all_positions = strpos_all($html, $needle);
var_dump($all_positions);
输出:
array(2)
[0]=>
int(3)
[1]=>
int(10)
或者用正则表达式作为针。
$html = "dddasdfdddasdffff";
$needle = "[d]3";
$all_positions = strpos_all($html, $needle);
var_dump($all_positions);
输出:
array(2)
[0]=>
int(0)
[1]=>
int(7)
【讨论】:
使用正则表达式查找子字符串不是一个好方法。当然你可以这样做,但正则表达式适用于更复杂的场景。在这种情况下,使用strpos
会简单得多,并且可以完成工作。【参考方案9】:
<?php
$mainString = "dddjmnpfdddjmnpffff";
$needle = "jmnp";
$lastPos = 0;
$positions = array();
while (($lastPos = strpos($html, $needle, $lastPos))!== false)
$positions[] = $lastPos;
$lastPos = $lastPos + strlen($needle);
// Displays 3 and 10
foreach ($positions as $value)
echo $value ."<br />";
?>
【讨论】:
【参考方案10】:另一种解决方案是使用explode()
:
public static function allSubStrPos($str, $del)
$searchArray = explode($del, $str);
unset($searchArray[count($searchArray) - 1]);
$positionsArray = [];
$index = 0;
foreach ($searchArray as $i => $s)
array_push($positionsArray, strlen($s) + $index);
$index += strlen($s) + strlen($del);
return $positionsArray;
【讨论】:
以上是关于PHP 查找字符串中所有出现的子字符串的主要内容,如果未能解决你的问题,请参考以下文章