startsWith () и endsWith () функции в PHP

Как я могу написать две функции, которые будут принимать строку и возвращаться, если она начинается с указанного символа / строки или заканчивается им?

Например:

$str = '|apples}'; echo startsWith($str, '|'); //Returns true echo endsWith($str, '}'); //Returns true 

 function startsWith($haystack, $needle) { $length = strlen($needle); return (substr($haystack, 0, $length) === $needle); } function endsWith($haystack, $needle) { $length = strlen($needle); return $length === 0 || (substr($haystack, -$length) === $needle); } 

Используйте это, если вы не хотите использовать регулярное выражение.

Можно использовать strrpos и strpos для проверки начала и конца, соответственно.

Обратите внимание, что использование strrpos для проверки начинается с и strpos для проверки концов с возвратом как можно скорее, а не проверкой всей строки до конца. Кроме того, это решение не создает временную строку. Подумайте, объясните причину, предшествующую downvoting. Просто потому, что f-wit в DWTF не понимает, как работает эта функция или думает, что есть только одно решение, это не значит, что этот ответ неверен.

 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 return $needle === "" || (($temp = strlen($haystack) - strlen($needle)) >= 0 && strpos($haystack, $needle, $temp) !== 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 будут превосходить эту функцию.

Обновлено 23 августа 2016 года

функции

 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

Все ответы до сих пор, похоже, выполняют множество ненужных работ, strlen calculations , string allocations (substr) и т. Д. Функции 'strpos' и 'stripos' возвращают индекс первого вхождения $needle в $haystack :

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

Кредит :

Проверьте, заканчивается ли строка другой строкой

Проверьте, начинается ли строка с другой строки

Регулярное выражение действует выше, но с другими настройками, также предложенными выше:

  function startsWith($needle, $haystack) { return preg_match('/^' . preg_quote($needle, '/') . '/', $haystack); } function endsWith($needle, $haystack) { return preg_match('/' . preg_quote($needle, '/') . '$/', $haystack); } 

Если скорость важна для вас, попробуйте это. (Я считаю, что это самый быстрый метод)

Работает только для строк, а если $ 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 

Я понимаю, что это было закончено, но вы можете посмотреть на strncmp, поскольку он позволяет вам сопоставить длину строки, поэтому:

 function startsWith($haystack, $needle, $case=true) { if ($case) return strncasecmp($haystack, $needle, strlen($needle)) == 0; else return strncmp($haystack, $needle, strlen($needle)) == 0; } 

Вот две функции, которые не вводят временную строку, которая может быть полезна, когда иглы существенно большие:

 function startsWith($haystack, $needle) { return strncmp($haystack, $needle, strlen($needle)) === 0; } function endsWith($haystack, $needle) { return $needle === '' || substr_compare($haystack, $needle, -strlen($needle)) === 0; } 

На этот вопрос уже много ответов, но в некоторых случаях вы можете решить что-то более простое, чем все. Если строка, которую вы ищете, известна (жестко запрограммирована), вы можете использовать регулярные выражения без кавычек и т. Д.

Проверьте, начинается ли строка с «ABC»:

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

заканчивается на «ABC»:

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

В моем простом случае я хотел проверить, заканчивается ли строка косой чертой:

 preg_match('/\/$/', $myPath); // slash has to be quoted 

Преимущество: поскольку он очень короткий и простой, вам не нужно определять функцию (например, endsWith() ), как показано выше.

Но опять же – это не решение для каждого случая, просто для этого конкретного.

Вы можете использовать strpos и strrpos

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

Короткие и легко понятные однострочники без регулярных выражений.

startsWith () – прямолинейный.

 function startsWith($haystack, $needle) { return (strpos($haystack, $needle) === 0); } 

endsWith () использует слегка причудливые и медленные strrev ():

 function endsWith($haystack, $needle) { return (strpos(strrev($haystack), strrev($needle)) === 0); } 

Сосредоточив внимание на startswith, если вы уверены, что строки не пустые, добавив тест на первый символ, перед сравнением, 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; 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 не выполняет итерацию всей строки (но даже в этом случае), это совсем не удобно.

Я надеюсь, что приведенный ниже ответ может быть эффективным и простым:

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

Обычно я в конечном итоге собираюсь с библиотекой, такой как 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 

Библиотека полна других удобных функций.

Функция substr может возвращать 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 } 

Тесты ( true означает хорошее):

 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

вкратце:

 function startsWith($str, $needle){ return substr($str, 0, strlen($needle)) === $needle; } function endsWith($str, $needle){ $length = strlen($needle); return !$length || substr($str, - $length) === $needle; } 

Ответ mpen невероятно тщательный, но, к сожалению, предоставленный эталонный тест имеет очень важный и пагубный надзор.

Поскольку каждый байт в иголках и стогах сена является полностью случайным, вероятность того, что пара с иголовыми сенами будет отличаться на самом первом байте, составляет 99.609375%, а это значит, что в среднем около 99609 из 100000 пар будут отличаться на самом первом байте , Другими словами, эталонный показатель в значительной степени предвзято для startswith реализациями, которые явно проверяют первый байт, как strncmp_startswith2 делает 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!<br />"; 

результаты тестов показывают немного другую историю:

 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 

Конечно, этот тест все еще не может быть абсолютно беспристрастным, но он проверяет эффективность алгоритмов при одновременном использовании игольчатых игл.

Это может сработать

 function startsWith($haystack, $needle) { return substr($haystack, 0, strlen($needle)) == $needle; } 

Источник: https://stackoverflow.com/a/4419658

Почему бы не следующее?

 //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!

Имейте в виду, strpos вернет false, если игла не была найдена в стоге сена, и вернет 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 () как

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

вернет true или false точно.

Кажется странным, что это просто, когда все дикие функции работают безудержными.

Я бы сделал это так

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

Основываясь на ответе Джеймса Блэка, вот его концы с версией:

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

Примечание. Я заменил часть if-else для функции запуска JamesWhite, поскольку strncasecmp – это фактически не зависящая от регистра версия strncmp.

Просто рекомендация:

 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 раз быстрее, когда я измерял). В истинном случае вы не платите практически никакой цены за производительность для этой отдельной линии, поэтому я думаю, что это стоит того. (Кроме того, на практике, когда вы тестируете множество строк для определенного начального фрагмента, большинство сравнений не сработают, поскольку в типичном случае вы что-то ищете).

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

Вот многобайтная безопасная версия принятого ответа, она отлично работает для строк 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); } 

Вы также можете использовать регулярные выражения:

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

Многие из предыдущих ответов будут работать так же хорошо. Однако это возможно так коротко, как вы можете это сделать, и делать то, что вам нужно. Вы просто заявляете, что хотите, чтобы он вернул true. Поэтому я включил решения, которые возвращают логическое значение 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'; } 

Вот эффективное решение для 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; } 

Не знаю, почему это так сложно для людей. Substr выполняет отличную работу и эффективен, так как вам не нужно искать всю строку, если она не соответствует.

Additionally, since I'm not checking integer values but comparing strings I don't have to necessarily have to worry about the strict === case. However, === is a good habit to get into.

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

or even better optimized.

 function startsWith($haystack,$needle) { return substring($haystack,0,strlen($needle)) == $needle); } function endsWith($haystack,$needle) { return substring($haystack,-strlen($needle)) == $needle); }