Как получить подстроку между двумя строками в PHP?

мне нужна функция, которая возвращает подстроку между двумя словами (или два символа). Мне интересно, есть ли функция php, которая достигает этого. Я не хочу думать о regex (ну, я мог бы сделать один, но действительно не думаю, что это лучший способ). Думал о strpos и substr функции. Вот пример:

$string = "foo I wanna a cake foo";

мы вызываем функцию: $substring = getInnerSubstring($string,"foo");
Он возвращается: "я хочу торт ".

спасибо заранее.

обновление: Ну, до сих пор я могу просто получить подстроку из двух слов в одной строке, вы позволите мне пойти немного дальше и спросить, могу ли я расширить использование getInnerSubstring($str,$delim) чтобы получить любые строки, которые находятся между значением delim, пример:

$string =" foo I like php foo, but foo I also like asp foo, foo I feel hero  foo";

Я получаю массив типа {"I like php", "I also like asp", "I feel hero"}.

30 ответов


Если строки разные (т. е.: [foo] & [/foo]), взгляните на этот пост от Джастина Кука. Я копирую его код ниже:

function get_string_between($string, $start, $end){
    $string = ' ' . $string;
    $ini = strpos($string, $start);
    if ($ini == 0) return '';
    $ini += strlen($start);
    $len = strpos($string, $end, $ini) - $ini;
    return substr($string, $ini, $len);
}

$fullstring = 'this is my [tag]dog[/tag]';
$parsed = get_string_between($fullstring, '[tag]', '[/tag]');

echo $parsed; // (result = dog)

регулярные выражения-это путь:

$str = 'before-str-after';
if (preg_match('/before-(.*?)-after/', $str, $match) == 1) {
    echo $match[1];
}

onlinePhp


function getBetween($string, $start = "", $end = ""){
    if (strpos($string, $start)) { // required if $start not exist in $string
        $startCharCount = strpos($string, $start) + strlen($start);
        $firstSubStr = substr($string, $startCharCount, strlen($string));
        $endCharCount = strpos($firstSubStr, $end);
        if ($endCharCount == 0) {
            $endCharCount = strlen($firstSubStr);
        }
        return substr($firstSubStr, 0, $endCharCount);
    } else {
        return '';
    }
}

пример использования:

echo getBetween("a","c","abc"); // returns: 'b'

echo getBetween("h","o","hello"); // returns: 'ell'

echo getBetween("a","r","World"); // returns: ''

function getInnerSubstring($string,$delim){
    // "foo a foo" becomes: array(""," a ","")
    $string = explode($delim, $string, 3); // also, we only need 2 items at most
    // we check whether the 2nd is set and return it, otherwise we return an empty string
    return isset($string[1]) ? $string[1] : '';
}

пример использования:

var_dump(getInnerSubstring('foo Hello world foo','foo'));
// prints: string(13) " Hello world "

если вы хотите удалить пробелы вокруг, используйте trim. Пример:

var_dump(trim(getInnerSubstring('foo Hello world foo','foo')));
// prints: string(11) "Hello world"

function getInbetweenStrings($start, $end, $str){
    $matches = array();
    $regex = "/$start([a-zA-Z0-9_]*)$end/";
    preg_match_all($regex, $str, $matches);
    return $matches[1];
}

например, вы хотите массив строк(ключей) между @@ в следующем например, где ' / ' не попадает между

$str = "C://@@ad_custom_attr1@@/@@upn@@/@@samaccountname@@";
$str_arr = getInbetweenStrings('@@', '@@', $str);

print_r($str_arr);

Если вы используете foo в качестве разделителя, затем посмотрите на explode()


Мне нравятся решения регулярных выражений, но ни один из других меня не устраивает.

Если вы знаете, что будет только 1 результат, вы можете использовать следующее:

$between = preg_replace('/(.*)BEFORE(.*)AFTER(.*)/sm', '', $string);

измените BEFORE и AFTER на нужные разделители.

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

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


<?php
  function getBetween($content,$start,$end){
    $r = explode($start, $content);
    if (isset($r[1])){
        $r = explode($end, $r[1]);
        return $r[0];
    }
    return '';
  }
?>

пример:

<?php 
  $content = "Try to find the guy in the middle with this function!";
  $start = "Try to find ";
  $end = " with this function!";
  $output = getBetween($content,$start,$end);
  echo $output;
?>

это вернет "парня в середине".


используйте функцию strstr php дважды.

$value = "This is a great day to be alive";
$value = strstr($value, "is"); //gets all text from needle on
$value = strstr($value, "be", true); //gets all text before needle
echo $value;

выходы: "is a great day to"


Если у вас есть несколько рецидивов из одной строки, и у вас есть другой шаблон [start] и [\end]. Вот функция, которая выводит массив.

function get_string_between($string, $start, $end){
    $split_string       = explode($end,$string);
    foreach($split_string as $data) {
         $str_pos       = strpos($data,$start);
         $last_pos      = strlen($data);
         $capture_len   = $last_pos - $str_pos;
         $return[]      = substr($data,$str_pos+1,$capture_len);
    }
    return $return;
}

здесь функция

function getInnerSubstring($string, $boundstring, $trimit=false) {
    $res = false;
    $bstart = strpos($string, $boundstring);
    if ($bstart >= 0) {
        $bend = strrpos($string, $boundstring);
        if ($bend >= 0 && $bend > $bstart)
            $res = substr($string, $bstart+strlen($boundstring), $bend-$bstart-strlen($boundstring));
    }
    return $trimit ? trim($res) : $res;
}

использовать его как

$string = "foo I wanna a cake foo";
$substring = getInnerSubstring($string, "foo");

echo $substring;

Output (обратите внимание, что он возвращает пробелы спереди и на и вашей строки, если они существуют)

Я хочу торт

если вы хотите обрезать результат функции как

$substring = getInnerSubstring($string, "foo", true);

результат: эта функция возвращает false если $boundstring не найден в $string или $boundstring существует только один раз в $string, в противном случае это возвращает подстроку между первым и последним вхождением $boundstring на $string.


ссылки

использование:

<?php

$str = "...server daemon started with pid=6849 (parent=6848).";
$from = "pid=";
$to = "(";

echo getStringBetween($str,$from,$to);

function getStringBetween($str,$from,$to)
{
    $sub = substr($str, strpos($str,$from)+strlen($from),strlen($str));
    return substr($sub,0,strpos($sub,$to));
}

?>

немного улучшенный код от GarciaWebDev и Henry Wang. Если заданы пустые $start или $end, функция возвращает значения от начала или до конца строки$. Также доступна опция Inclusive, хотим ли мы включить результат поиска или нет:

function get_string_between ($string, $start, $end, $inclusive = false){
    $string = " ".$string;

    if ($start == "") { $ini = 0; }
    else { $ini = strpos($string, $start); }

    if ($end == "") { $len = strlen($string); }
    else { $len = strpos($string, $end, $ini) - $ini;}

    if (!$inclusive) { $ini += strlen($start); }
    else { $len += strlen($end); }

    return substr($string, $ini, $len);
}

Я должен добавить что-то к сообщению Юлия Тильвикаса. Я искал решение, подобное этому, которое он описал в своем посте. Но я думаю, что это ошибка. Я не получаю строку между двумя строками, я также получаю больше с этим решением, потому что мне нужно вычесть длину начальной строки. Когда это делается, я действительно получаю строку между двумя строками.

вот мои изменения своего решения:

function get_string_between ($string, $start, $end, $inclusive = false){
    $string = " ".$string;

    if ($start == "") { $ini = 0; }
    else { $ini = strpos($string, $start); }

    if ($end == "") { $len = strlen($string); }
    else { $len = strpos($string, $end, $ini) - $ini - strlen($start);}

    if (!$inclusive) { $ini += strlen($start); }
    else { $len += strlen($end); }

    return substr($string, $ini, $len);
}

Greetz

V


попробуйте это, его работа для меня, получить данные между тегами тест слово.

$str = "Xdata test HD01 test 1data";  
$result = explode('test',$str);   
print_r($result);
echo $result[1];

в PHP strpos стиль это вернет false если начальная отметка sm или конечный знак em не нашли.

этот результат (false) is разные из пустой строки это то, что вы получаете, если между начальными и конечными метками ничего нет.

function between( $str, $sm, $em )
{
    $s = strpos( $str, $sm );
    if( $s === false ) return false;
    $s += strlen( $sm );
    $e = strpos( $str, $em, $s );
    if( $e === false ) return false;
    return substr( $str, $s, $e - $s );
}

функция вернет только первое совпадение.

это очевидно, но стоит упомянуть, что функция сначала будет искать sm и тогда для em.

это означает, что вы не можете получить желаемый результат / поведение, если em должна быть найдены, а затем строка должна быть проанализирована назад в поисках sm.


Не php pro. но недавно я тоже наткнулся на эту стену, и вот что я придумал.

function tag_contents($string, $tag_open, $tag_close){
   foreach (explode($tag_open, $string) as $key => $value) {
       if(strpos($value, $tag_close) !== FALSE){
            $result[] = substr($value, 0, strpos($value, $tag_close));;
       }
   }
   return $result;
}

$string = "i love cute animals, like [animal]cat[/animal],
           [animal]dog[/animal] and [animal]panda[/animal]!!!";

echo "<pre>";
print_r(tag_contents($string , "[animal]" , "[/animal]"));
echo "</pre>";

//result
Array
(
    [0] => cat
    [1] => dog
    [2] => panda
)

Я использую

if (count(explode("<TAG>", $input))>1){
      $content = explode("</TAG>",explode("<TAG>", $input)[1])[0];
}else{
      $content = "";
}

Subtitue для любого разделителя, который вы хотите.


использование:

function getdatabetween($string, $start, $end){
    $sp = strpos($string, $start)+strlen($start);
    $ep = strpos($string, $end)-strlen($start);
    $data = trim(substr($string, $sp, $ep));
    return trim($data);
}
$dt = "Find string between two strings in PHP";
echo getdatabetween($dt, 'Find', 'in PHP');

У меня были некоторые проблемы с функцией get_string_between (), используемой здесь. Поэтому я пришел со своей версией. Может, это поможет людям в том же деле, что и мне.

protected function string_between($string, $start, $end, $inclusive = false) { 
   $fragments = explode($start, $string, 2);
   if (isset($fragments[1])) {
      $fragments = explode($end, $fragments[1], 2);
      if ($inclusive) {
         return $start.$fragments[0].$end;
      } else {
         return $fragments[0];
      }
   }
   return false;
}

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

<?php

// substr_getbykeys() - Returns everything in a source string that exists between the first occurance of each of the two key substrings
//          - only returns first match, and can be used in loops to iterate through large datasets
//          - arg 1 is the first substring to look for
//          - arg 2 is the second substring to look for
//          - arg 3 is the source string the search is performed on.
//          - arg 4 is boolean and allows you to determine if returned result should include the search keys.
//          - arg 5 is boolean and can be used to determine whether search should be case-sensative or not.
//

function substr_getbykeys($key1, $key2, $source, $returnkeys, $casematters) {
    if ($casematters === true) {
        $start = strpos($source, $key1);
        $end = strpos($source, $key2);
    } else {
        $start = stripos($source, $key1);
        $end = stripos($source, $key2);
    }
    if ($start === false || $end === false) { return false; }
    if ($start > $end) {
        $temp = $start;
        $start = $end;
        $end = $temp;
    }
    if ( $returnkeys === true) {
        $length = ($end + strlen($key2)) - $start;
    } else {
        $start = $start + strlen($key1);
        $length = $end - $start;
    }
    return substr($source, $start, $length);
}

// substr_delbykeys() - Returns a copy of source string with everything between the first occurance of both key substrings removed
//          - only returns first match, and can be used in loops to iterate through large datasets
//          - arg 1 is the first key substring to look for
//          - arg 2 is the second key substring to look for
//          - arg 3 is the source string the search is performed on.
//          - arg 4 is boolean and allows you to determine if returned result should include the search keys.
//          - arg 5 is boolean and can be used to determine whether search should be case-sensative or not.
//

function substr_delbykeys($key1, $key2, $source, $returnkeys, $casematters) {
    if ($casematters === true) {
        $start = strpos($source, $key1);
        $end = strpos($source, $key2);
    } else {
        $start = stripos($source, $key1);
        $end = stripos($source, $key2);
    }
    if ($start === false || $end === false) { return false; }
    if ($start > $end) {
        $temp = $start; 
        $start = $end;
        $end = $temp;
    }
    if ( $returnkeys === true) {
        $start = $start + strlen($key1);
        $length = $end - $start;
    } else {
        $length = ($end + strlen($key2)) - $start;  
    }
    return substr_replace($source, '', $start, $length);
}
?>

С некоторой ошибкой. В частности, большинство представленных функций требуют существования $end, когда на самом деле в моем случае мне нужно было, чтобы он был необязательным. Используйте это $end необязательно, и оцените для FALSE, если $start не существует вообще:

function get_string_between( $string, $start, $end ){
    $string = " " . $string;
    $start_ini = strpos( $string, $start );
    $end = strpos( $string, $end, $start+1 );
    if ($start && $end) {
        return substr( $string, $start_ini + strlen($start), strlen( $string )-( $start_ini + $end ) );
    } elseif ( $start && !$end ) {
        return substr( $string, $start_ini + strlen($start) );
    } else {
        return FALSE;
    }

}

UTF-8 версия @Alejandro Iglesias ответ, будет работать для нелатинских символов:

function get_string_between($string, $start, $end){
    $string = ' ' . $string;
    $ini = mb_strpos($string, $start, 0, 'UTF-8');
    if ($ini == 0) return '';
    $ini += mb_strlen($start, 'UTF-8');
    $len = mb_strpos($string, $end, $ini, 'UTF-8') - $ini;
    return mb_substr($string, $ini, $len, 'UTF-8');
}

$fullstring = 'this is my [tag]dog[/tag]';
$parsed = get_string_between($fullstring, '[tag]', '[/tag]');

echo $parsed; // (result = dog)

Это функция, которую я использую для этого. Я объединил два ответа в одной функции для одного или нескольких разделителей.

function getStringBetweenDelimiters($p_string, $p_from, $p_to, $p_multiple=false){
    //checking for valid main string  
    if (strlen($p_string) > 0) {
        //checking for multiple strings 
        if ($p_multiple) {
            // getting list of results by end delimiter
            $result_list = explode($p_to, $p_string);
            //looping through result list array 
            foreach ( $result_list AS $rlkey => $rlrow) {
                // getting result start position
                $result_start_pos   = strpos($rlrow, $p_from);
                // calculating result length
                $result_len         =  strlen($rlrow) - $result_start_pos;

                // return only valid rows
                if ($result_start_pos > 0) {
                    // cleanying result string + removing $p_from text from result
                    $result[] =   substr($rlrow, $result_start_pos + strlen($p_from), $result_len);                 
                }// end if 
            } // end foreach 

        // if single string
        } else {
            // result start point + removing $p_from text from result
            $result_start_pos   = strpos($p_string, $p_from) + strlen($p_from);
            // lenght of result string
            $result_length      = strpos($p_string, $p_to, $result_start_pos);
            // cleaning result string
            $result             = substr($p_string, $result_start_pos+1, $result_length );
        } // end if else 
    // if empty main string
    } else {
        $result = false;
    } // end if else 

    return $result;


} // end func. get string between

для простого использования (возвращает два):

$result = getStringBetweenDelimiters(" one two three ", 'one', 'three');

для получения каждой строки в таблице результирующего массива:

$result = getStringBetweenDelimiters($table, '<tr>', '</tr>', true);

есть лучшее решение для этого из tonyspiro

function getBetween($content,$start,$end){
   $r = explode($start, $content);
   if (isset($r[1])){
       $r = explode($end, $r[1]);
       return $r[0];
   }
   return '';
}

улучшение Алехандро!--5-->. Вы можете оставить $start или $end аргументы пустые, и он будет использовать начало или конец строки.

echo get_string_between("Hello my name is bob", "my", ""); //output: " name is bob"

private function get_string_between($string, $start, $end){ // Get
    if($start != ''){ //If $start is empty, use start of the string
        $string = ' ' . $string;
        $ini = strpos($string, $start);
        if ($ini == 0) return '';
        $ini += strlen($start);
    }
    else{
        $ini = 0;
    }

    if ($end == '') { //If $end is blank, use end of string
        return substr($string, $ini);
    }
    else{
        $len = strpos($string, $end, $ini) - $ini; //Work out length of string
        return substr($string, $ini, $len);
    }
}

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

grabstring ("тестовая строка","","",0) возвращает тестовую строку
grabstring ("Test string", "Test","", 0) возвращает string
grabstring ("тестовая строка","s","", 5) возвращает string

function grabstring($strSource,$strPre,$strPost,$StartAt) {
if(@strpos($strSource,$strPre)===FALSE && $strPre!=""){
    return("");
}
@$Startpoint=strpos($strSource,$strPre,$StartAt)+strlen($strPre);
if($strPost == "") {
    $EndPoint = strlen($strSource);
} else {
    if(strpos($strSource,$strPost,$Startpoint)===FALSE){
        $EndPoint= strlen($strSource);
    } else {
        $EndPoint = strpos($strSource,$strPost,$Startpoint);
    }
}
if($strPre == "") {
    $Startpoint = 0;
}
if($EndPoint - $Startpoint < 1) {
    return "";
} else {
        return substr($strSource, $Startpoint, $EndPoint - $Startpoint);
}

}


function strbtwn($s,$start,$end){
    $i = strpos($s,$start);
    $j = strpos($s,$end,$i);
    return $i===false||$j===false? false: substr(substr($s,$i,$j-$i),strlen($start));
}

использование:

echo strbtwn($s,"<h2>","</h2>");//<h2>:)</h2> --> :)

'/s'

function getStrBetween($left, $right, $in)
{
    preg_match('/'.$left.'(.*?)'.$right.'/s', $in, $match);
    return empty($match[1]) ? NULL : $match[1];
}

попробуйте это ;)


echo explode('/', explode(')', $string)[0])[1];

замените ' / ' на ваш первый символ/строку и ')' на ваш конечный символ / строку. :)