Я понимаю, что эта функция получит первое вхождение строки.
Но то, что я хочу, это второе вхождение.
Как это сделать?
Я понимаю, что эта функция получит первое вхождение строки.
Но то, что я хочу, это второе вхождение.
Как это сделать?
Вам нужно указать смещение для начала поиска как необязательный третий параметр и рассчитать его, начав поиск сразу после первого появления, добавив длину того, что вы ищете, к местоположению, в котором вы его нашли.
$pos1 = strpos($haystack, $needle);
$pos2 = strpos($haystack, $needle, $pos1 + strlen($needle));
Я знаю, что этот вопрос старый, но вот функция, которую я написал, чтобы получить X-ое появление подстроки, что может быть полезно для других людей, у которых есть эта проблема, и наткнуться на этот поток.
/**
* Find the position of the Xth occurrence of a substring in a string
* @param $haystack
* @param $needle
* @param $number integer > 0
* @return int
*/
function strposX($haystack, $needle, $number){
if($number == '1'){
return strpos($haystack, $needle);
}elseif($number > '1'){
return strpos($haystack, $needle, strposX($haystack, $needle, $number - 1) + strlen($needle));
}else{
return error_log('Error: Value for parameter $number is out of range');
}
}
Рекурсивная функция из Smokey_Bud резко замедлила мой скрипт. Использование регулярного выражения намного быстрее в этом случае (для нахождения любого случая):
function strposX($haystack, $needle, $number)
{
// decode utf8 because of this behaviour: https://bugs.php.net/bug.php?id=37391
preg_match_all("/$needle/", utf8_decode($haystack), $matches, PREG_OFFSET_CAPTURE);
return $matches[0][$number-1][1];
}
// get position of second 'wide'
$pos = strposX('Hello wide wide world', 'wide', 2);
Чтобы найти второе вхождение строки, вы можете использовать strpos вместе с параметром "offset", добавив предыдущее смещение в strpos.
$source = "Hello world, how you doing world...world ?";
$find = "world";
$offset = 0;
$findLength = strlen($find);
$occurrence = 0;
while (($offset = strpos($source, $find, $offset))!== false) {
if ($occurrence ++) {
break;
}
$offset += $findLength;
}
echo $offset;
Вы можете найти все вхождения, сохранив смещение в массиве
while (($offset = strpos($source, $find, $offset))!== false) {
$occurrences[] = $offset;
$offset += $findLength;
}
var_export($occurrences);
Или может получить конкретное вхождение, сопоставив $ вхождение
//find 3rd occurrence
if ($occurrence ++ == 2) {
break;
}
Вы можете попробовать это, хотя я его не тестировал -
$pos = strpos($haystack, $needle, strpos($haystack, $needle)+strlen($needle));
Просто красиво
function strposX($haystack, $needle, $n = 0)
{
$offset = 0;
for ($i = 0; $i < $n; $i++) {
$pos = strpos($haystack, $needle, $offset);
if ($pos !== false) {
$offset = $pos + strlen($needle);
} else {
return false;
}
}
return $offset;
}
$offset = strposX($result, "\n", $n);
if ($offset === false) {
$offset = strlen($result) - 1;
}
просто работал у меня, чтобы найти, если есть 2 или более появление char, а затем strlen их я обнаружил, что существуют 2 вхождения ex (я вообще не использую $match):
$string = '1234|6|#red';
if(strlen(preg_match_all('/|/', $string,$matches, PREG_OFFSET_CAPTURE)) ==2){
echo 'i have 2 occurence of char: |';
}
Старый вопрос, но если кто-то ищет способ найти вхождения из END строки (например, 3-е вхождение точки с конца), работает следующая функция (не хотела использовать функцию oncodes, чтобы не испортить кодирование)
$str = "NooooYesYesNo";
function find_occurence_from_end($haystack, $needle, $num) {
for ($i=1; $i <=$num ; $i++) {
# first loop return position of needle
if($i == 1) {
$pos = strrpos($haystack, $needle);
}
# subsequent loops trim haystack to pos and return needle new position
if($i != 1) {
$haystack = substr($haystack, 0, $pos);
$pos = strrpos($haystack, $needle);
}
}
return $pos;
}
$pos = find_occurence_from_end($str, "Yes", 2);
// 5
Это супер просто. В основном каждый раз, когда он обнаруживает появление вашей иглы, он "обрезает" строку в эту позицию. Таким образом, он продолжает обрезать его, возвращая последнюю позицию каждый раз.
Старый вопрос, но как насчет использования explode
?
$corpus = "how many words are there in a dictionary? I'm not going to count them word by word...";
$looking_for = 'word';
$instance = 2;
$parts = explode($looking_for, $corpus, $instance + 1);
array_pop($parts);
$position = strlen(implode($looking_for, $parts));
function substr_Index( $str, $nth ){
$str2 = '';
$posTotal = 0;
for($i=0; $i < $nth; $i++){
if($str2 != ''){
$str = $str2;
}
$pos = strpos($str, ':');
$str2 = substr($str, $pos+1);
$posTotal += $pos+1;
}
return $posTotal-1;
}
echo substr($mystring, substr_Index( $mystring , 2) );
Функция возвращает позицию n-го разделителя.
Второй параметр substr_Index
должен быть больше 0;
Чтобы найти второй случай, используйте substr_Index( $mystring, 2)
Легко, просто сделай это:
$i = $pos = 0;
do {
$pos = strpos( $string, $needle, $pos+1 );
} while( $i++ < $nth);
$ nth для вашей ситуации равно 2.
Пожалуйста, проверьте следующий код... он работает очень хорошо для меня.
<?php
function f_srch ($s1, $par) {
echo 'Searching for [' . $par . '] in [' . $s1 . ']<br>';
$k = 0; //while loop
$i = 0; // counter
while ($k >= 0) {
$pos = strpos($s1, $par, $k);
if ($pos === false) {
$k=-1;
echo 'Letter not found'.'<br>';
} else {
if ($pos == $k) {
echo 'The position of the letter is '.$pos.'<br>';
$i++;
}
$k++;
}
}
echo 'The letter was found ' . $i . ' time(s).'.'<br>';
}
f_srch('i am searching for a letter in this sentence','t');
?>
$newstring = 'abcdef abcdef';
$pos = strpos($newstring, 'a', 1); // $pos = 7, not 0