我试图提取一个子字符串。 我需要在PHP中做一些帮助。
以下是一些我正在使用的示例字符串以及需要的结果:
home/cat1/subcat2 => home
test/cat2 => test
startpage => startpage
我想直到第一个/都得到字符串,但是如果没有/存在,则得到整个字符串。
我试过了,
substr($mystring, 0, strpos($mystring, ‘/’))
我认为它说-获取/的位置,然后从位置0到该位置获取子字符串。
我不知道如何处理没有/的情况,而不会使语句太大。
有没有一种方法也可以处理这种情况而又不会使PHP语句过于复杂?
您可能会发现s($str)->beforeFirst()很有帮助,如在该独立库中所发现的。
最有效的解决方案是strtok函数:
strtok($mystring, ‘/’)
例如:
$mystring = ‘home/cat1/subcat2/’;
$first = strtok($mystring, ‘/’);
echo $first; // home
和
$mystring = ‘home’;
$first = strtok($mystring, ‘/’);
echo $first; // home
这也比current-explode解决方案快40%。 (并不是我经常使用它,以至于很重要。)
这是优雅而快速的-应该是公认的答案。
这应该是例外的答案。与给定的任何explode解决方案相比,绝对更快,并且内存和CPU周期效率更高。
strtok的问题是firstsecond将返回first,但是second将返回second而不是空字符串。
除了上面的评论之外,PHP 4.1.0更改了发现空白部分的行为。旧的行为返回了一个空字符串,而新的正确行为仅跳过了字符串的一部分
辉煌。比使用爆炸要干净得多,然后必须索引到数组中。首选解决方案。
使用explode()
$arr = explode(“/”, $string, 2);
$first = $arr[0];
在这种情况下,我对explode使用了limit参数,以便php扫描字符串的次数不会超过所需数量。
+1感谢您的回答。它起作用:)但是有一个问题。我只能执行此操作-> $arr = explode(,$mystring,2); echo $arr[0];。我无法在一个语句本身中获取第一个字符串-echo explode(,$mystring,2)[0];。由于explode返回一个数组,因此我应该能够正确执行吗?但是我得到一个错误。有什么建议么?
不,你不能那样做。
PHP不喜欢您索引函数的返回值。
哦。好的。如果可能的话,那会很好。
list($first,) = explode(“”, $string, 2);
explode() + [0]是编写strtok($string,””)的漫长方式
请参阅下面使用current()的AndyBrandys优雅解决方案
创建一个全新的数组是否过大?那就是explode的作用。
顺便说一句,您可以在php 5.5中做explode(” /”,$ string,2)[0]
@mario strtok()的问题是firstsecond将返回first,但是second将返回second而不是空字符串。
$first = explode(“/”, $string)[0];
优雅,但在计算机时间上效率不高。但是如今,人们不再关心分钟的CPU周期
那这个呢 :
substr($mystring.’/’, 0, strpos($mystring, ‘/’))
只需在mystring的末尾添加一个” /”,就可以确保至少有一个;)
接受答案的单行版本:
$out=explode(“/”, $mystring, 2)[0];
应该可以在PHP 5.4+
其更好的答案如stackoverflow.com/a/8679361/4217744
这可能是我想到的最短的例子:
list($first) = explode(“/”, $mystring);
1)如果找到定界符,list()将自动分配字符串,直到”/”
2)如果找不到定界符”/”,则将分配整个字符串
…并且如果您真的迷恋性能,则可以添加额外的参数来爆炸explode(“/”, $mystring, 2),这会限制返回的元素的最大值。
我喜欢这种方法。节省了不必要的数组。并且strtok()是不安全的。
@ rybo111:strtok()有什么不安全之处?
@ rybo111我回响了哈克雷斯的情感;是什么使strtok()不安全?
@hakre请参阅我对jmarcelis答复的答复。根据PHP版本,它可能导致意外行为。
PHP 4.1.0-拉力赛?
@hakre如果youre> 4.1.0(我希望您是),则该行为可能不是您所期望的,因为它将跳过空标记。
令牌不能为空,并且该行为已记录在案。令牌始终从第一个字节开始,而不是分隔符。也就是说,永远不会有空令牌。这很有用,特别是对于始终需要第一个段或另一个上段的路径分隔符。 firstsecondthird
@hakre这个问题的标题说”在第一个/之前获取字符串”-strtok不会严格执行该操作(如您的示例),这就是我的观点。
OP给出了一个示例,该示例声明第一个令牌的长度为非零,而strtok正是针对OP的情况-因此,如果您谈论严格性,即使您跳过文档,strtok也不会出现意外行为。
迟到总比没有好。 php为此具有预定义的功能。这是个好方法。
如果要在匹配之前得到零件,只需将before_needle(第3个参数)设置为true
http://php.net/manual/zh/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’, ‘/’)
);
如果您不能确定线中是否存在针头,则使用此方法不安全。
@fooquency —正确,但是可以确保将字符始终添加到要检查的字符串的末尾。
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 );
}
}
我还没有测试过,但这应该可以正常工作。而且速度也很快
为strstr() +1,但是要注意,如果字符串不包含$needle,它将返回false,因此上述explode()解决方案更适合这种情况。
您可以创建一个辅助函数来解决这个问题:
/**
* 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
在explode上使用current将简化此过程。
$str = current(explode(“/”, $str, 2));
如今,电流给非变量带来了误差。
您可以尝试使用这样的正则表达式:
$s = preg_replace(‘|/.*$|’, ”, $s);
有时,尽管regex速度较慢,所以如果性能是一个问题,请确保对其进行基准测试,并在更适合您的情况下使用带有子字符串的其他替代方法。
正则表达式也可能过于矫kill过正,但是既然我对explode说的也一样,那么看看哪种更快会很有趣。
这绝对没有错,我想不出为什么要配2张反对票。我个人不会使用正则表达式,但是它肯定没有错。
$string=”kalion/home/public_html”;
$newstring=( stristr($string,”/”)==FALSE ) ? $string : substr($string,0,stripos($string,”/”));
为什么不使用:
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);
}
我认为这应该工作吗?
substr($mystring, 0, (($pos = (strpos($mystring, ‘/’) !== false)) ? $pos : strlen($mystring)));
您的函数将始终返回第一个字符,因为您正在执行(strpos($ mystring,/)!== false),然后再将其分配给$ pos,您需要执行(($ pos = strpos($ firstColumnName,_) )!== false)。这将是发布问题的人正在寻找的1个班轮。