PHP子字符串提取。获取第一个'/'之前的字符串或整个字符串


170

我试图提取一个子字符串。我需要在PHP中做些帮助。

这是我正在使用的一些示例字符串以及所需的结果:

home/cat1/subcat2 => home

test/cat2 => test

startpage => startpage

我想将字符串保留到第一个/,但是如果不/存在,请获取整个字符串。

我试过了,

substr($mystring, 0, strpos($mystring, '/'))

我认为它说-获取位置,/然后从位置0到位置获取子字符串。

我不知道如何处理不存在的情况/,而又不会使声明太大。

是否有办法在不使PHP语句过于复杂的情况下处理这种情况?


1
s($str)->beforeFirst('/')如在该独立库中所发现的,您可能会有所帮助。
caw 2016年

Answers:


261

explode()

$arr = explode("/", $string, 2);
$first = $arr[0];

在这种情况下,我使用limit参数来explode使php不会扫描字符串超过所需的范围。


2
+1感谢您的回答。它起作用:)但是有一个问题。我只能这样做-> $arr = explode('/',$mystring,2); echo $arr[0];。我无法在一个语句本身中获取第一个字符串- echo explode('/',$mystring,2)[0];。由于explode返回一个数组,我应该能够做到这一点吗?但是我得到一个错误。有什么建议?

1
PHP不喜欢您索引函数的返回值。
gnud

3
哦。好的。如果可能的话,那会很好。

36
explode() + [0]是一种漫长的写作方式strtok($string, "/")
mario'Mar

5
顺便说一句,您可以在php 5.5中做explode(“ /”,$ string,2)[0]
billynoah 2014年

293

最有效的解决方案是strtok功能:

strtok($mystring, '/')

例如:

$mystring = 'home/cat1/subcat2/';
$first = strtok($mystring, '/');
echo $first; // home

$mystring = 'home';
$first = strtok($mystring, '/');
echo $first; // home

25
这也比current-explode解决方案快40%。(不是我经常使用它,而是要紧。)
towr 2014年

5
这是优雅而快速的-应该是公认的答案。
Kosta Kontos

5
这应该是例外的答案。与explode给定的任何解决方案相比,它绝对更快,内存和CPU周期更高。
Shivam Maheshwari

问题strtokfirst/second将返回first/second将返回second而不是空字符串。
rybo111 '16

除了上面的评论之外,PHP 4.1.0更改了发现空白部分的行为。旧的行为返回了一个空字符串,而新的正确行为仅跳过了字符串的一部分
rybo111 '16

95
$first = explode("/", $string)[0];

2
优雅,但在计算机时间上效率不高。但是这些天人们不再关心分钟的CPU周期
Dennis

13

那这个呢 :

substr($mystring.'/', 0, strpos($mystring, '/'))

只需在mystring的末尾添加“ /”,就可以确保至少有一个;)


您可以先检查字符串中是否有一个斜杠,然后再执行此操作。无论如何,这是最简单的解决方案。
Guilherme Sampaio

12

接受答案的单行版本:

$out=explode("/", $mystring, 2)[0];

应该可以在PHP 5.4+


1
与下面的不同,“ 2”限制了它创建的数组项的数量。好想法。
Ben在CA

9

这可能是我想到的最短的例子:

list($first) = explode("/", $mystring);

1)list()将自动分配字符串,直到"/"找到分隔符为止
2)如果"/"未找到分隔符,则将分配整个字符串

...如果您真的迷恋性能,则可以添加额外的参数来爆炸explode("/", $mystring, 2),从而限制返回的元素的最大值。


2
我喜欢这种方法。节省了不必要的数组。而且strtok()是不安全的。
rybo111 '16

1
@ rybo111:什么是不安全的strtok()
哈克尔(Hakre)'17

@ rybo111我回应哈克雷的观点;是什么使strtok()不安全?
Doktor J

@hakre请参阅我对jmarceli的答复。根据PHP版本,它可能导致意外行为。
rybo111

PHP 4.1.0-拉力赛?
hakre

8

迟到总比没有好。php为此具有预定义的功能。这是个好方法。

strstr

如果您想在比赛之前获得零件,只需将before_needle(第3个参数)设置为true http://php.net/manual/en/function.strstr.php

function not_strtok($string, $delimiter)
{    
    $buffer = strstr($string, $delimiter, true);

    if (false === $buffer) {
        return $string;
    }

    return $buffer;
}

var_dump(
    not_strtok('st/art/page', '/')
);

如果您不能确定针是否在弦中,则使用此方法不安全。
愚蠢的人2016年

@fooquency —正确,但是可以确保将字符始终添加到要检查的字符串的末尾。
MikeSchinkel '19

谢谢。我的测试表明,该strstr速度比稍快strtok。我会和前者一起去。
伊恩Y.19年

5

PHP 5.3中的strstr()函数应该可以完成此工作。但是,第三个参数应该设置为true。

但是,如果您未使用5.3,则下面的功能应该可以正常工作:

function strbstr( $str, $char, $start=0 ){
    if ( isset($str[ $start ]) && $str[$start]!=$char ){
        return $str[$start].strbstr( $str, $char, $start+1 );
    }
}

我还没有测试过,但是应该可以正常工作。而且速度也很快


3
为+1 strstr(),但请注意,false如果字符串不包含$needle,则返回,因此上述explode()解决方案更适合这种情况。
本杰明·

3

您可以创建一个辅助函数来解决这个问题:

/**
 * Return string before needle if it exists.
 *
 * @param string $str
 * @param mixed $needle
 * @return string
 */
function str_before($str, $needle)
{
    $pos = strpos($str, $needle);

    return ($pos !== false) ? substr($str, 0, $pos) : $str;
}

这是一个用例:

$sing = 'My name is Luka. I live on the second floor.';

echo str_before($sing, '.'); // My name is Luka

3

您可以尝试使用这样的正则表达式:

$s = preg_replace('|/.*$|', '', $s);

有时,尽管regex速度较慢,所以如果性能是一个问题,请确保对其进行基准测试,并在更适合您的情况下使用带有子字符串的其他替代方法。


2
正则表达式也可能过于矫kill过正,但是既然我也这么说explode,那么看看哪种更快会很有趣。
rvighne 2014年

1
绝对没有错,我也想不出为什么要配两票。我个人不会使用正则表达式,但是肯定没有错。
billynoah's

2

使用currenton explode可以简化过程。

 $str = current(explode("/", $str, 2));

0
$string="kalion/home/public_html";

$newstring=( stristr($string,"/")==FALSE ) ? $string : substr($string,0,stripos($string,"/"));

0

您也可以使用这一解决方案

list($substring) = explode("/", $string);

-1

我认为这应该工作吗?

substr($mystring, 0, (($pos = (strpos($mystring, '/') !== false)) ? $pos : strlen($mystring)));

您的函数将始终返回第一个字符,因为您正在执行(strpos($ mystring,'/')!== false),然后再将其分配给$ pos,您需要执行((($ pos = strpos($ firstColumnName, '_'))!== false)这将是发布问题的人正在寻找的1个班轮。
Mihai P.

-1

为什么不使用:

function getwhatiwant($s)
{
    $delimiter='/';
    $x=strstr($s,$delimiter,true);
    return ($x?$x:$s);
}

要么:

   function getwhatiwant($s)
   {
       $delimiter='/';
       $t=explode($delimiter, $s);
       return ($t[1]?$t[0]:$s);
   }
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.