如何在PHP中的两个字符串之间获取子字符串?


142

我需要一个函数来返回两个单词(或两个字符)之间的子字符串。我想知道是否有实现该功能的php函数。我不想考虑正则表达式(嗯,我可以做一个,但真的不认为这是最好的方法)。思维strpossubstr功能。这是一个例子:

$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"}


2
如果您已经在使用Laravel,那就\Illuminate\Support\Str::between('This is my name', 'This', 'name');方便了。laravel.com/docs/7.x/helpers#method-str-between
瑞安

Answers:


324

如果字符串不同(即[foo]和[/ foo]),请查看Justin Cook的这篇文章。我在下面复制他的代码:

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)

7
对该函数进行了修改,使其包含开始和结束。<code>函数string_between($ string,$ start,$ end,$ inclusive = false){$ string =“”。$ string; $ ini = strpos($ string,$ start); 如果($ ini == 0)返回“”;如果(!$ inclusive)$ ini + = strlen($ start); $ len = strpos($ string,$ end,$ ini)-$ ini; 如果(包含$)$ len + = strlen($ end); 返回substr($ string,$ ini,$ len); } </ code>
亨利

2
是否可以扩展此功能,以便可以返回两个字符串?假设我有一个$ fullstring的“ [tag] dogs [/ tag]和[tag] cats [/ tag]”,我想要一个包含“ dogs”和“ cats”的数组。
伦纳德·舒茨2015年

1
@LeonardSchuetz – 然后尝试此答案
leymannx

“ [tag] dogs [/ tag]和[tag] cats [/ tag]”仍未回答。如何以数组形式获取“狗”和“猫”?请指教。
罗姆尼克·苏萨

1
有人回答了我的问题!您可以访问此stackoverflow.com/questions/35168463/...
Romnick苏萨


22
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("abc","a","c"); // returns: 'b'

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

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

5
顺便说一句,您的“示例使用”段落是错误的。参数的顺序完全错误。
那本

15
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"

1
这很整洁,因为它是单行的,但不幸的是,它仅限于具有唯一的定界符,即,如果需要“ foo”和“ bar”之间的子字符串,则必须使用其他策略。
mastazi '17

13
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);

3
当它是$ start或$ end变量时,请不要忘记像“ \ /”一样转义“ /”。
LubošRemplík

10

两次使用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"


8

我喜欢正则表达式解决方案,但其他都不适合我。

如果您知道只有1个结果,则可以使用以下方法:

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

将之前和之后更改为所需的定界符。

另外请记住,如果没有匹配项,此函数将返回整个字符串。

该解决方案是多行的,但是您可以根据需要使用修饰符。


7

不是PHP专业版。但是我最近也碰到了这堵墙,这就是我想出的。

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
)

6

如果您foo用作分隔符,请查看explode()


是的,我们可以使用分解数组的第一个索引来获得所需的结果。(不是零)。
captain_a

6
<?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;
?>

这将返回“中间人”。


3

如果单个字符串有多个重复出现,并且具有不同的[开始]和[\ 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;
}

3

这是一个功能

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;

输出(请注意,如果存在,它将返回字符串的and前面和后面的空格)

我想吃蛋糕

如果要修剪结果,请使用类似

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

结果:该函数将返回,如果$boundstring在没有被发现$string,或者$boundstring只存在一次$string,否则它返回的第一个和最后发生之间串$boundstring$string


参考资料


您使用的是不带括号的if子句,但您可能知道这是个坏主意?
xmoex

@xmoex,IF您在说什么子句?也许我打错了字,但老实说,我现在看不到任何奇怪的东西。IF我在上面的函数中使用的两个s都具有适当的包围括号的条件。第一个IF也有包围两行的大括号(花括号),第二个IF不需要'em,因为它是单行代码。我缺少什么?
Wh1T3h4Ck5

我说的是单行。我以为您的帖子的编辑删除了它,但是后来我发现它根本不在那儿。如果您将来更改代码,这是有时很难发现错误的常见原因。
xmoex

@xmoex 非常不同意。在从事将近20年的业务后,我可以说括号是导致错误的极少数原因(无论如何都需要适当的缩进)。用大括号括起来的单行是丑陋的(观点要点),并使代码更大(事实要点)。在大多数公司中,在代码完成时都需要删除不必要的括号。没错,对于经验不足的用户,在调试过程中可能很难发现它,但这不是全球性的问题,只是他们学习道路上的一步。就我个人而言,即使在复杂的嵌套情况下,牙套也从未遇到过大问题。
Wh1T3h4Ck5

@ Wh1T3h4Ck5我尊重您的意见和经验,但我一点也不相信。从系统的角度来看,花括号不会使代码变大。它扩大了文件的大小,但是编译器在乎什么呢?如果使用js,您可能会在上线之前自动丑陋的代码。我认为使用牙套总会
减轻

3

亚历杭德罗答案的改进。您可以将$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);
    }
}

1

用:

<?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));
}

?>

1

GarciaWebDev和Henry Wang的代码有所改进。如果给出了空的$ start或$ end,函数将返回$ string开头或结尾的值。无论我们是否要包括搜索结果,“包容”选项也都可用:

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);
}

1

我必须在Julius Tilvikas的帖子中添加一些内容。我正在寻找他在帖子中描述的解决方案。但是我认为这是一个错误。我并没有真正了解两个字符串之间的字符串,我还可以通过此解决方案获得更多,因为我必须减去起始字符串的长度。这样做时,我的确得到两个字符串之间的字符串。

这是我对他的解决方案的更改:

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);
}

格蕾兹

V


1

试试这个,它对我的​​工作,获取测试词之间的数据。

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

1

如果未找到开始标记或结束标记,则以PHP strpos样式返回。falsesmem

结果(false空字符串不同,空字符串是您在开始和结束标记之间没有任何内容时所得到的。

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


1

这就是我正在使用的功能。我将两个答案合并在一个函数中,用于单个或多个定界符。

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);

1

我用

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

将<TAG>替换为所需的任何定界符。


1

亚历杭德罗·加西亚·伊格莱西亚斯发表的内容的编辑版本。

这使您可以根据发现结果的次数来选择要获取的字符串的特定位置。

function get_string_between_pos($string, $start, $end, $pos){
    $cPos = 0;
    $ini = 0;
    $result = '';
    for($i = 0; $i < $pos; $i++){
      $ini = strpos($string, $start, $cPos);
      if ($ini == 0) return '';
      $ini += strlen($start);
      $len = strpos($string, $end, $ini) - $ini;
      $result = substr($string, $ini, $len);
      $cPos = $ini + $len;
    }
    return $result;
  }

用法:

$text = 'string has start test 1 end and start test 2 end and start test 3 end to print';

//get $result = "test 1"
$result = $this->get_string_between_pos($text, 'start', 'end', 1);

//get $result = "test 2"
$result = $this->get_string_between_pos($text, 'start', 'end', 2);

//get $result = "test 3"
$result = $this->get_string_between_pos($text, 'start', 'end', 3);

strpos有一个附加的可选输入,以在特定点开始搜索。因此,我将先前的位置存储在$ cPos中,以便再次进行for循环检查时,它从停止处的结尾开始。


1

我想这里的绝大多数答案都不会回答编辑过的部分。正如一个答案所提到的,可以使用正则表达式来完成。我有不同的方法。


此函数搜索$ string并找到之间第一个字符串 $ start和$ end,从$ offset位置开始。然后,它更新$ offset位置以指向结果的开始。如果$ includeDelimiters为true,则在结果中包括定界符。

如果找不到$ start或$ end字符串,则返回null。如果$ string,$ start或$ end为空字符串,它也会返回null。

function str_between(string $string, string $start, string $end, bool $includeDelimiters = false, int &$offset = 0): ?string
{
    if ($string === '' || $start === '' || $end === '') return null;

    $startLength = strlen($start);
    $endLength = strlen($end);

    $startPos = strpos($string, $start, $offset);
    if ($startPos === false) return null;

    $endPos = strpos($string, $end, $startPos + $startLength);
    if ($endPos === false) return null;

    $length = $endPos - $startPos + ($includeDelimiters ? $endLength : -$startLength);
    if (!$length) return '';

    $offset = $startPos + ($includeDelimiters ? 0 : $startLength);

    $result = substr($string, $offset, $length);

    return ($result !== false ? $result : null);
}

以下函数查找两个字符串之间的所有字符串(无重叠)。它需要上一个函数,并且参数相同。执行后,$ offset指向最后找到的结果字符串的开头。

function str_between_all(string $string, string $start, string $end, bool $includeDelimiters = false, int &$offset = 0): ?array
{
    $strings = [];
    $length = strlen($string);

    while ($offset < $length)
    {
        $found = str_between($string, $start, $end, $includeDelimiters, $offset);
        if ($found === null) break;

        $strings[] = $found;
        $offset += strlen($includeDelimiters ? $found : $start . $found . $end); // move offset to the end of the newfound string
    }

    return $strings;
}

例子:

str_between_all('foo 1 bar 2 foo 3 bar', 'foo', 'bar')[' 1 ', ' 3 ']

str_between_all('foo 1 bar 2', 'foo', 'bar')[' 1 ']

str_between_all('foo 1 foo 2 foo 3 foo', 'foo', 'foo')[' 1 ', ' 3 ']

str_between_all('foo 1 bar', 'foo', 'foo')[]


0

用:

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');

0

我在这里使用的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;
}

0

早些写了这些,发现它对于广泛的应用程序非常有用。

<?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);
}
?>

0

有一些错误捕获。具体来说,所提供的大多数功能都需要$ end存在,而实际上就我而言,我需要将其为可选。使用这个是$ end是可选的,如果$ start根本不存在,则评估为FALSE:

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;
    }

}

0

@Alejandro Iglesias答案的UTF-8版本适用于非拉丁字符:

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)

0

tonyspiro获得了最佳解决方案

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

0

使用此小功能可以轻松完成此操作:

function getString($string, $from, $to) {
    $str = explode($from, $string);
    $str = explode($to, $str[1]);
    return $s[0];
}
$myString = "<html>Some code</html>";
print getString($myString, '<html>', '</html>');

// Prints: Some code

-1

我已经使用了多年,效果很好。可能可以提高效率,但是

grabstring(“测试字符串”,“”,“,0)返回测试字符串
grabstring(”测试字符串“,”测试“,”“,0)返回字符串
grabstring(”测试字符串“,” s“,”“, 5)返回字符串

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);
}

}

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.