php with函数,string - PHP中的startsWith()和endsWith()函数

本文介绍了如何在PHP中实现startsWith()和endsWith()函数,用于检查字符串是否以指定字符或字符串开头或结尾。讨论了多种实现方法,包括使用strpos、substr、strcmp等内置函数,以及正则表达式的解决方案。还提供了性能基准测试,以选择最佳实践。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

string - PHP中的startsWith()和endsWith()函数

我如何编写两个带字符串的函数,如果它以指定的字符/字符串开头或以它结尾,则返回?

例如:

$str = '|apples}';

echo startsWith($str, '|'); //Returns true

echo endsWith($str, '}'); //Returns true

30个解决方案

1355 votes

function startsWith($haystack, $needle)

{

$length = strlen($needle);

return (substr($haystack, 0, $length) === $needle);

}

function endsWith($haystack, $needle)

{

$length = strlen($needle);

if ($length == 0) {

return true;

}

return (substr($haystack, -$length) === $needle);

}

如果您不想使用正则表达式,请使用此选项。

MrHus answered 2018-12-20T12:58:42Z

945 votes

可以使用strrpos和strncmp分别检查start-with和ends-with。

请注意,使用strncmp开始检查和substr_compare检查结束将尽快返回,而不是检查整个字符串直到结束。 此外,此解决方案不会创建临时字符串。 考虑在downvoting之前解释原因。 仅仅因为DWTF的f-wit不理解这个功能是如何工作的,或者认为只有一个解决方案并不意味着这个答案是错误的。

function startsWith($haystack, $needle) {

// search backwards starting from haystack length characters from the end

return $needle === ''

|| strrpos($haystack, $needle, -strlen($haystack)) !== false;

}

function endsWith($haystack, $needle) {

// search forward starting from end minus needle length characters

if ($needle === '') {

return true;

}

$diff = \strlen($haystack) - \strlen($needle);

return $diff >= 0 && strpos($haystack, $needle, $diff) !== false;

}

测试和结果(与此相比):

startsWith('abcdef', 'ab') -> true

startsWith('abcdef', 'cd') -> false

startsWith('abcdef', 'ef') -> false

startsWith('abcdef', '') -> true

startsWith('', 'abcdef') -> false

endsWith('abcdef', 'ab') -> false

endsWith('abcdef', 'cd') -> false

endsWith('abcdef', 'ef') -> true

endsWith('abcdef', '') -> true

endsWith('', 'abcdef') -> false

注意:strncmp和substr_compare函数将胜过此函数。

Salman A answered 2018-12-20T12:59:16Z

220 votes

更新于2016年8月23日

功能

function substr_startswith($haystack, $needle) {

return substr($haystack, 0, strlen($needle)) === $needle;

}

function preg_match_startswith($haystack, $needle) {

return preg_match('~' . preg_quote($needle, '~') . '~A', $haystack) > 0;

}

function substr_compare_startswith($haystack, $needle) {

return substr_compare($haystack, $needle, 0, strlen($needle)) === 0;

}

function strpos_startswith($haystack, $needle) {

return strpos($haystack, $needle) === 0;

}

function strncmp_startswith($haystack, $needle) {

return strncmp($haystack, $needle, strlen($needle)) === 0;

}

function strncmp_startswith2($haystack, $needle) {

return $haystack[0] === $needle[0]

? strncmp($haystack, $needle, strlen($needle)) === 0

: false;

}

测试

echo 'generating tests';

for($i = 0; $i < 100000; ++$i) {

if($i % 2500 === 0) echo '.';

$test_cases[] = [

random_bytes(random_int(1, 7000)),

random_bytes(random_int(1, 3000)),

];

}

echo "done!\n";

$functions = ['substr_startswith', 'preg_match_startswith', 'substr_compare_startswith', 'strpos_startswith', 'strncmp_startswith', 'strncmp_startswith2'];

$results = [];

foreach($functions as $func) {

$start = microtime(true);

foreach($test_cases as $tc) {

$func(...$tc);

}

$results[$func] = (microtime(true) - $start) * 1000;

}

asort($results);

foreach($results as $func => $time) {

echo "$func: " . number_format($time, 1) . " ms\n";

}

结果(PHP 7.0.9)

(分类最快到最慢)

strncmp_startswith2: 40.2 ms

strncmp_startswith: 42.9 ms

substr_compare_startswith: 44.5 ms

substr_startswith: 48.4 ms

strpos_startswith: 138.7 ms

preg_match_startswith: 13,152.4 ms

结果(PHP 5.3.29)

(分类最快到最慢)

strncmp_startswith2: 477.9 ms

strpos_startswith: 522.1 ms

strncmp_startswith: 617.1 ms

substr_compare_startswith: 706.7 ms

substr_startswith: 756.8 ms

preg_match_startswith: 10,200.0 ms

startswith_benchmark.php

mpen answered 2018-12-20T13:00:06Z

130 votes

到目前为止所有答案似乎做了大量不必要的工作,strlen calculations,2139666379885560833等.'strpos'和'stripos'函数返回string allocations (substr)6中第一次出现的索引:$needle:

function startsWith($haystack,$needle,$case=true)

{

if ($case)

return strpos($haystack, $needle, 0) === 0;

return stripos($haystack, $needle, 0) === 0;

}

function endsWith($haystack,$needle,$case=true)

{

$expectedPosition = strlen($haystack) - strlen($needle);

if ($case)

return strrpos($haystack, $needle, 0) === $expectedPosition;

return strripos($haystack, $needle, 0) === $expectedPosition;

}

Sander Rijken answered 2018-12-20T13:00:27Z

45 votes

function startsWith($haystack, $needle, $case = true) {

if ($case) {

return (strcmp(substr($haystack, 0, strlen($needle)), $needle) === 0);

}

return (strcasecmp(substr($haystack, 0, strlen($needle)), $needle) === 0);

}

function endsWith($haystack, $needle, $case = true) {

if ($case) {

return (strcmp(substr($haystack, strlen($haystack) - strlen($needle)), $needle) === 0);

}

return (strcasecmp(substr($haystack, strlen($haystack) - strlen($needle)), $needle) === 0);

}

归功于:

检查字符串是否以另一个字符串结尾

检查字符串是否以另一个字符串开头

KdgDev answered 2018-12-20T13:00:55Z

26 votes

上面的正则表达式功能,但上面提到的其他调整:

function startsWith($needle, $haystack) {

return preg_match('/^' . preg_quote($needle, '/') . '/', $haystack);

}

function endsWith($needle, $haystack) {

return preg_match('/' . preg_quote($needle, '/') . '$/', $haystack);

}

tridian answered 2018-12-20T13:01:15Z

21 votes

如果速度对你很重要,试试这个。(我相信这是最快的方法)

仅适用于字符串,如果$ haystack只有1个字符

function startsWithChar($needle, $haystack)

{

return ($needle[0] === $haystack);

}

function endsWithChar($needle, $haystack)

{

return ($needle[strlen($needle) - 1] === $haystack);

}

$str='|apples}';

echo startsWithChar($str,'|'); //Returns true

echo endsWithChar($str,'}'); //Returns true

echo startsWithChar($str,'='); //Returns false

echo endsWithChar($str,'#'); //Returns false

lepe answered 2018-12-20T13:01:40Z

16 votes

这里有两个不引入临时字符串的函数,当针大得多时,它可能很有用:

function startsWith($haystack, $needle)

{

return strncmp($haystack, $needle, strlen($needle)) === 0;

}

function endsWith($haystack, $needle)

{

return $needle === '' || substr_compare($haystack, $needle, -strlen($needle)) === 0;

}

Ja͢ck answered 2018-12-20T13:02:00Z

16 votes

这个问题已经有很多答案,但在某些情况下,你可以选择比所有这些更简单的东西。如果您要查找的字符串是已知的(硬编码),则可以使用正则表达式而无需任何引用等。

检查字符串是否以'ABC'开头:

preg_match('/^ABC/', $myString); // "^" here means beginning of string

以'ABC'结尾:

preg_match('/ABC$/', $myString); // "$" here means end of string

在我的简单案例中,我想检查字符串是否以斜杠结尾:

preg_match('#/$#', $myPath); // Use "#" as delimiter instead of escaping slash

优点:由于它非常简短,您不必定义如上所示的功能(例如endsWith())。

但同样 - 这不是每个案例的解决方案,只是这个非常具体的案例。

noamtm answered 2018-12-20T13:02:42Z

15 votes

我意识到这已经完成,但你可能想看一下strncmp因为它允许你把字符串的长度进行比较,所以:

function startsWith($haystack, $needle, $case=true) {

if ($case)

return strncasecmp($haystack, $needle, strlen($needle)) == 0;

else

return strncmp($haystack, $needle, strlen($needle)) == 0;

}

James Black answered 2018-12-20T13:03:02Z

10 votes

您可以使用strrpos和strrpos

$bStartsWith = strpos($sHaystack, $sNeedle) == 0;

$bEndsWith = strrpos($sHaystack, $sNeedle) == strlen($sHaystack)-strlen($sNeedle);

Lex answered 2018-12-20T13:03:22Z

7 votes

简短易懂的单行,没有正则表达式。

startsWith()是直截了当的。

function startsWith($haystack, $needle) {

return (strpos($haystack, $needle) === 0);

}

endsWith()使用稍微花哨和缓慢的strrev():

function endsWith($haystack, $needle) {

return (strpos(strrev($haystack), strrev($needle)) === 0);

}

Dan answered 2018-12-20T13:03:51Z

6 votes

专注于startwith,如果你确定字符串不是空的,在比较之前在第一个字符串上添加测试,strlen等等,会加快速度:

function startswith5b($haystack, $needle) {

return ($haystack{0}==$needle{0})?strncmp($haystack, $needle, strlen($needle)) === 0:FALSE;

}

它以某种方式(20%-30%)更快。 添加另一个char测试,比如$ haystack {1} === $ needle {1}似乎不会加速,甚至可能会放慢速度。

===似乎比==快条件运算符(a)?b:c似乎比if(a) b; else c;快

对于那些问“为什么不使用strpos?”的人 称其他解决方案“不必要的工作

strpos很快,但它不适合这项工作。

要理解,这里有一个小模拟作为例子:

Search a12345678c inside bcdefga12345678xbbbbb.....bbbbba12345678c

计算机在“内部”做什么?

With strccmp, etc...

is a===b? NO

return false

With strpos

is a===b? NO -- iterating in haysack

is a===c? NO

is a===d? NO

....

is a===g? NO

is a===g? NO

is a===a? YES

is 1===1? YES -- iterating in needle

is 2===3? YES

is 4===4? YES

....

is 8===8? YES

is c===x? NO: oh God,

is a===1? NO -- iterating in haysack again

is a===2? NO

is a===3? NO

is a===4? NO

....

is a===x? NO

is a===b? NO

is a===b? NO

is a===b? NO

is a===b? NO

is a===b? NO

is a===b? NO

is a===b? NO

...

... may many times...

...

is a===b? NO

is a===a? YES -- iterating in needle again

is 1===1? YES

is 2===3? YES

is 4===4? YES

is 8===8? YES

is c===c? YES YES YES I have found the same string! yay!

was it at position 0? NOPE

What you mean NO? So the string I found is useless? YEs.

Damn.

return false

假设strlen没有迭代整个字符串(但即使在那种情况下),这根本不方便。

FrancescoMM answered 2018-12-20T13:04:43Z

6 votes

这些天我通常最终会使用像underscore-php这样的库。

require_once("vendor/autoload.php"); //use if needed

use Underscore\Types\String;

$str = "there is a string";

echo( String::startsWith($str, 'the') ); // 1

echo( String::endsWith($str, 'ring')); // 1

该库充满了其他方便的功能。

yuvilio answered 2018-12-20T13:05:07Z

6 votes

mpen的答案非常彻底,但不幸的是,提供的基准测试具有非常重要和有害的监督。

因为针和草堆中的每个字节都是完全随机的,针 - 草堆对在第一个字节上的差异是99.609375%,这意味着,平均而言,100000对中的大约99609在第一个字节上会有所不同。 换句话说,基准测试严重偏向startswith实现,它们明确地检查第一个字节,如strncmp_startswith2所示。

如果测试生成循环实现如下:

echo 'generating tests';

for($i = 0; $i < 100000; ++$i) {

if($i % 2500 === 0) echo '.';

$haystack_length = random_int(1, 7000);

$haystack = random_bytes($haystack_length);

$needle_length = random_int(1, 3000);

$overlap_length = min(random_int(0, $needle_length), $haystack_length);

$needle = ($needle_length > $overlap_length) ?

substr($haystack, 0, $overlap_length) . random_bytes($needle_length - $overlap_length) :

substr($haystack, 0, $needle_length);

$test_cases[] = [$haystack, $needle];

}

echo " done!
";

基准测试结果说明了一个略有不同的故事

strncmp_startswith: 223.0 ms

substr_startswith: 228.0 ms

substr_compare_startswith: 238.0 ms

strncmp_startswith2: 253.0 ms

strpos_startswith: 349.0 ms

preg_match_startswith: 20,828.7 ms

当然,这个基准测试可能仍然不是完全不偏不倚的,但是当给出部分匹配的针时,它也会测试算法的效率。

Veeno answered 2018-12-20T13:05:46Z

6 votes

这是接受答案的多字节安全版本,适用于UTF-8字符串:

function startsWith($haystack, $needle)

{

$length = mb_substr($needle, 'UTF-8');

return (mb_substr($haystack, 0, $length, 'UTF-8') === $needle);

}

function endsWith($haystack, $needle)

{

$length = mb_strlen($needle, 'UTF-8');

return $length === 0 ||

(mb_substr($haystack, -$length, $length, 'UTF-8') === $needle);

}

Vahid Amiri answered 2018-12-20T13:06:06Z

6 votes

最快的结束()解决方案:

# Checks if a string ends in a string

function endsWith($haystack, $needle) {

return substr($haystack,-strlen($needle))===$needle;

}

基准测试:

# This answer

function endsWith($haystack, $needle) {

return substr($haystack,-strlen($needle))===$needle;

}

# Accepted answer

function endsWith2($haystack, $needle) {

$length = strlen($needle);

return $length === 0 ||

(substr($haystack, -$length) === $needle);

}

# Second most-voted answer

function endsWith3($haystack, $needle) {

// search forward starting from end minus needle length characters

if ($needle === '') {

return true;

}

$diff = \strlen($haystack) - \strlen($needle);

return $diff >= 0 && strpos($haystack, $needle, $diff) !== false;

}

# Regex answer

function endsWith4($haystack, $needle) {

return preg_match('/' . preg_quote($needle, '/') . '$/', $haystack);

}

function timedebug() {

$test = 10000000;

$time1 = microtime(true);

for ($i=0; $i < $test; $i++) {

$tmp = endsWith('TestShortcode', 'Shortcode');

}

$time2 = microtime(true);

$result1 = $time2 - $time1;

for ($i=0; $i < $test; $i++) {

$tmp = endsWith2('TestShortcode', 'Shortcode');

}

$time3 = microtime(true);

$result2 = $time3 - $time2;

for ($i=0; $i < $test; $i++) {

$tmp = endsWith3('TestShortcode', 'Shortcode');

}

$time4 = microtime(true);

$result3 = $time4 - $time3;

for ($i=0; $i < $test; $i++) {

$tmp = endsWith4('TestShortcode', 'Shortcode');

}

$time5 = microtime(true);

$result4 = $time5 - $time4;

echo $test.'x endsWith: '.$result1.' seconds # This answer
';

echo $test.'x endsWith2: '.$result4.' seconds # Accepted answer
';

echo $test.'x endsWith3: '.$result2.' seconds # Second most voted answer
';

echo $test.'x endsWith4: '.$result3.' seconds # Regex answer
';

exit;

}

timedebug();

基准结果:

10000000x endsWith: 1.5760900974274 seconds # This answer

10000000x endsWith2: 3.7102129459381 seconds # Accepted answer

10000000x endsWith3: 1.8731069564819 seconds # Second most voted answer

10000000x endsWith4: 2.1521229743958 seconds # Regex answer

Lucas Bustamante answered 2018-12-20T13:06:34Z

5 votes

我希望以下答案可能有效且简单:

$content = "The main string to search";

$search = "T";

//For compare the begining string with case insensitive.

if(stripos($content, $search) === 0) echo 'Yes';

else echo 'No';

//For compare the begining string with case sensitive.

if(strpos($content, $search) === 0) echo 'Yes';

else echo 'No';

//For compare the ending string with case insensitive.

if(stripos(strrev($content), strrev($search)) === 0) echo 'Yes';

else echo 'No';

//For compare the ending string with case sensitive.

if(strpos(strrev($content), strrev($search)) === 0) echo 'Yes';

else echo 'No';

Srinivasan.S answered 2018-12-20T13:06:54Z

4 votes

在许多特殊情况下,substr_compare函数可以返回false,所以这是我的版本,它处理这些问题:

function startsWith( $haystack, $needle ){

return $needle === ''.substr( $haystack, 0, strlen( $needle )); // substr's false => empty string

}

function endsWith( $haystack, $needle ){

$len = strlen( $needle );

return $needle === ''.substr( $haystack, -$len, $len ); // ! len=0

}

测试(substr_compare意味着好):

var_dump( startsWith('',''));

var_dump( startsWith('1',''));

var_dump(!startsWith('','1'));

var_dump( startsWith('1','1'));

var_dump( startsWith('1234','12'));

var_dump(!startsWith('1234','34'));

var_dump(!startsWith('12','1234'));

var_dump(!startsWith('34','1234'));

var_dump('---');

var_dump( endsWith('',''));

var_dump( endsWith('1',''));

var_dump(!endsWith('','1'));

var_dump( endsWith('1','1'));

var_dump(!endsWith('1234','12'));

var_dump( endsWith('1234','34'));

var_dump(!endsWith('12','1234'));

var_dump(!endsWith('34','1234'));

另外,substr_compare功能也值得期待。[http://www.php.net/manual/en/function.substr-compare.php]

biziclop answered 2018-12-20T13:07:23Z

4 votes

简而言之:

function startsWith($str, $needle){

return substr($str, 0, strlen($needle)) === $needle;

}

function endsWith($str, $needle){

$length = strlen($needle);

return !$length || substr($str, - $length) === $needle;

}

Vincent Pazeller answered 2018-12-20T13:07:43Z

3 votes

这可能有效

function startsWith($haystack, $needle) {

return substr($haystack, 0, strlen($needle)) == $needle;

}

资料来源:[https://stackoverflow.com/a/4419658]

user507410 answered 2018-12-20T13:08:07Z

3 votes

为什么不以下?

//How to check if a string begins with another string

$haystack = "valuehaystack";

$needle = "value";

if (strpos($haystack, $needle) === 0){

echo "Found " . $needle . " at the beginning of " . $haystack . "!";

}

输出:

在valuehaystack的开头找到了价值!

请记住,如果在大海捞针中找不到针,则返回假,并且当且仅当在索引0处找到针时才会返回0(开始时为AKA)。

以下是:

$haystack = "valuehaystack";

$needle = "haystack";

//If index of the needle plus the length of the needle is the same length as the entire haystack.

if (strpos($haystack, $needle) + strlen($needle) === strlen($haystack)){

echo "Found " . $needle . " at the end of " . $haystack . "!";

}

在这种情况下,不需要函数startsWith()as

(strpos($stringToSearch, $doesItStartWithThis) === 0)

将准确地返回真或假。

这看起来很奇怪,所有野外功能在这里都很猖獗。

Kade Hafen answered 2018-12-20T13:08:58Z

3 votes

我会这样做的

function startWith($haystack,$needle){

if(substr($haystack,0, strlen($needle))===$needle)

return true;

}

function endWith($haystack,$needle){

if(substr($haystack, -strlen($needle))===$needle)

return true;

}

Jelle Keizer answered 2018-12-20T13:09:19Z

3 votes

只是一个建议:

function startsWith($haystack,$needle) {

if($needle==="") return true;

if($haystack[0]<>$needle[0]) return false;

if(substr_compare($haystack,$needle,0,strlen($needle))==0) return true;

return false;

}

额外的一行,比较字符串的第一个字符,可以使虚假案件立即返回,因此进行了许多比较更快(当我测量时快7倍)。 在真实的情况下,您为该单行支付几乎没有性价比,所以我认为值得包括。 (另外,在实践中,当您为特定的起始块测试许多字符串时,大多数比较都会失败,因为在典型的情况下,您正在寻找某些内容。)

dkellner answered 2018-12-20T13:09:44Z

2 votes

基于詹姆斯布莱克的答案,这是它的两个版本:

function startsWith($haystack, $needle, $case=true) {

if ($case)

return strncmp($haystack, $needle, strlen($needle)) == 0;

else

return strncasecmp($haystack, $needle, strlen($needle)) == 0;

}

function endsWith($haystack, $needle, $case=true) {

return startsWith(strrev($haystack),strrev($needle),$case);

}

注意:我已经为James Black的startsWith函数交换了if-else部分,因为strncasecmp实际上是strncmp的不区分大小写的版本。

bobo answered 2018-12-20T13:10:08Z

2 votes

您还可以使用正则表达式:

function endsWith($haystack, $needle, $case=true) {

return preg_match("/.*{$needle}$/" . (($case) ? "" : "i"), $haystack);

}

Freeman answered 2018-12-20T13:10:28Z

2 votes

许多以前的答案也会起作用。 然而,这可能是你可以做到的最短,并让它做你想要的。 你只是声明你希望它“回归真实”。 所以我已经包含了返回布尔值true / false和文本true / false的解决方案。

// boolean true/false

function startsWith($haystack, $needle)

{

return strpos($haystack, $needle) === 0 ? 1 : 0;

}

function endsWith($haystack, $needle)

{

return stripos($haystack, $needle) === 0 ? 1 : 0;

}

// textual true/false

function startsWith($haystack, $needle)

{

return strpos($haystack, $needle) === 0 ? 'true' : 'false';

}

function endsWith($haystack, $needle)

{

return stripos($haystack, $needle) === 0 ? 'true' : 'false';

}

wynshaft answered 2018-12-20T13:10:49Z

1 votes

这是PHP 4的有效解决方案。如果在PHP 5上使用substr_compare而不是strcasecmp(substr(...)),则可以获得更快的结果。

function stringBeginsWith($haystack, $beginning, $caseInsensitivity = false)

{

if ($caseInsensitivity)

return strncasecmp($haystack, $beginning, strlen($beginning)) === 0;

else

return strncmp($haystack, $beginning, strlen($beginning)) === 0;

}

function stringEndsWith($haystack, $ending, $caseInsensitivity = false)

{

if ($caseInsensitivity)

return strcasecmp(substr($haystack, strlen($haystack) - strlen($ending)), $haystack) === 0;

else

return strpos($haystack, $ending, strlen($haystack) - strlen($ending)) !== false;

}

Patrick Smith answered 2018-12-20T13:11:09Z

-1 votes

$ends_with = strrchr($text, '.'); // Ends with dot

$start_with = (0 === strpos($text, '.')); // Starts with dot

ymakux answered 2018-12-20T13:11:25Z

-3 votes

不知道为什么这对人们来说太难了。 Substr做得很好并且效率很高,因为如果它不匹配,你不需要搜索整个字符串。

另外,因为我没有检查整数值但是比较字符串我不必担心严格的===情况。 但是,===是一个很好的习惯。

function startsWith($haystack,$needle) {

substring($haystack,0,strlen($needle)) == $needle) { return true; }

return false;

}

function endsWith($haystack,$needle) {

if(substring($haystack,-strlen($needle)) == $needle) { return true; }

return false;

}

甚至更好地优化。

function startsWith($haystack,$needle) {

return substring($haystack,0,strlen($needle)) == $needle);

}

function endsWith($haystack,$needle) {

return substring($haystack,-strlen($needle)) == $needle);

}

Spoo answered 2018-12-20T13:11:54Z

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值