Efficient way to get last part of string only afte

2019-08-18 07:35发布

What is an efficient way to get the part of a string after the occurrence of a certain needle, only if that needle is at the start of the haystack. Similar to strstr(), but excluding the needle, and only when found at the beginning of the string.

If it isn't found, it should preferably return false.

I have the feeling I'm overlooking some very obvious PHP functions here, but I can't seem to think of them right now.

For example:

$basePath = '/some/dir/';

$result = some_function( '/some/dir/this/is/the/relative/part', $basePath );
/*
should return:
this/is/the/relative/part
*/

$result = some_function( '/fake/dir/this/is/the/relative/part', $basePath );
$result = some_function( '/pre/some/dir/this/is/the/relative/part', $basePath );
/*
last example has '/some/dir/' in it, but not at start.
should both preferably return:
false
*/

I'll be using this for a filesystem service that should act as a sandbox, and should be able to give out and take in paths, relative to the base sand box directory.

标签: php substring
6条回答
Evening l夕情丶
2楼-- · 2019-08-18 07:55

This case calls for strncmp:

function some_function($path, $base) {
    if (strncmp($path, $base, $n = strlen($base)) == 0) {
        return substr($path, $n);
    }
}
查看更多
爷的心禁止访问
3楼-- · 2019-08-18 07:56

How about regular expressions?

$regexp = preg_quote($basepath, '/');
return preg_replace("/^$regexp/", "", $path);
查看更多
我命由我不由天
4楼-- · 2019-08-18 07:59

Put more simply than the other examples:

function some_function($path,$base){
  $baselen = strlen($base);
  if (strpos($path,$base) === 0 && strlen($path)>$baselen)
    return substr($path,$baselen);
  return false;
}

DEMO

Alternate using strncmp, too: DEMO

查看更多
狗以群分
5楼-- · 2019-08-18 08:00
function some_function($path, $basePath) {
    $pos = strpos($path, $basePath);
    if ($pos !== false) {
        return substr($path, strlen($basePath));
    } else {
        return false;
    }
}

But what about this?

some_function('/base/path/../../secret/password.txt', '/base/path/safe/dir/');

You likely want to call realpath() on $path first, so that it is fully simplified, before using some_function().

查看更多
迷人小祖宗
6楼-- · 2019-08-18 08:09
function some_function($haystack, $baseNeedle) {
   if (! preg_match('/^' . preg_quote($baseNeedle, '/') . '(.*)$/', $haystack, $matches)) {
      return false;
   }
   return $matches[1];
}
查看更多
▲ chillily
7楼-- · 2019-08-18 08:12

Not sure if there's a built-in function for this.

function some_function($str1, $str2) {
  $l = strlen($str2);
  if (substr($str1, 0, $l) == $str2)
    return substr($str1, $l);
  else
    return false;
}

For long $str1 and short $str2, I think this is going to be faster than using strpos.

If you're using this for paths, you might want to do some checking if the slashes are at the right place.

查看更多
登录 后发表回答