Вопрос по поводу strpos.Как получить второе вхождение строки? - PullRequest
46 голосов
/ 27 июня 2010

Я понимаю, что эта функция получит первое вхождение строки.

Но что я хочу, это второе вхождение.

Как это сделать?

Ответы [ 12 ]

48 голосов
/ 27 июня 2010

Вам необходимо указать смещение для начала поиска в качестве необязательного третьего параметра и рассчитать его, начав поиск сразу после первого вхождения, добавив длину того, что вы ищете, к местоположению, в котором вы его нашли.

$pos1 = strpos($haystack, $needle);
$pos2 = strpos($haystack, $needle, $pos1 + strlen($needle));
46 голосов
/ 03 сентября 2013

Я знаю, что этот вопрос довольно старый, но вот функция, которую я написал для получения 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');
    }
}
10 голосов
/ 09 сентября 2016

Рекурсивная функция из 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);
9 голосов
/ 03 января 2017

Чтобы найти второе вхождение строки, вы можете использовать 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;
}
8 голосов
/ 27 июня 2010

Вы можете попробовать это, хотя я не проверял это -

$pos = strpos($haystack, $needle, strpos($haystack, $needle)+strlen($needle));
3 голосов
/ 22 сентября 2016

Просто красиво

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;
}
0 голосов
/ 17 апреля 2019
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)

0 голосов
/ 09 апреля 2019

Старый вопрос, но как насчет использования 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));
0 голосов
/ 15 декабря 2017

Старый вопрос, но если кто-то ищет способ найти вхождения в конце строки (например, 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's 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

Это супер просто.По сути, каждый раз, когда он находит вхождение вашей иглы, он «обрезает» нить до этой позиции.Таким образом, он продолжает обрезать его, возвращая последнюю позицию каждый раз.

0 голосов
/ 20 августа 2016

только что работал для меня, чтобы найти, если есть 2 или более вхождения символа, то, найдя их, я нашел, что существует 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: |';

    }
...