функции functionsWith () и окончание () в PHP

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

Например:

$str = '|apples}';

echo startsWith($str, '|'); //Returns true
echo endsWith($str, '}'); //Returns true
7.05.2009 12:14:27
Посмотрите класс Str Laravel startWith () и endWith () для хорошо протестированных методов. Пограничные случаи встречались, поэтому широкое использование этого кода является преимуществом.
Gras Double 6.12.2014 23:32:04
Вы можете найти s($str)->startsWith('|')и s($str)->endsWith('}')помочь, как найти в этой автономной библиотеке .
caw 26.07.2016 23:46:47
Предупреждение: большинство ответов здесь ненадежны в многобайтовых кодировках, таких как UTF-8.
Álvaro González 15.05.2017 14:07:31
Следуя моим комментариям, вы можете использовать последнюю версию (на сегодня 5.4 ). Примечательно, что launchWith () был оптимизирован для больших строк сена.
Gras Double 22.05.2017 18:51:11
30 ОТВЕТОВ
РЕШЕНИЕ
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);
}

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

1597
17.08.2018 13:51:41
+1 Это чище, чем принятый ответ. Кроме того, $lengthне требуется в последней строке endsWith().
too much php 17.09.2009 02:57:33
Я бы сказал, что конец-с ('foo', '') == false - это правильное поведение. Потому что foo не заканчивается ничем. «Foo» оканчивается на «o», «oo» и «Foo».
MrHus 13.04.2012 13:34:58
Концы могут быть написаны намного короче:return substr($haystack, -strlen($needle))===$needle;
Rok Kralj 11.06.2012 09:57:45
Вы можете избежать ifвовсе, передав в $lengthкачестве третьего параметра substr: return (substr($haystack, -$length, $length);. Это обрабатывает случай $length == 0, возвращая пустую строку, а не всю $haystack.
mxxk 23.01.2015 01:21:18
@MrHus Я бы порекомендовал использовать многобайтовые безопасные функции, например, mb_strlen и mb_substr
19Gerhard85 25.04.2016 08:49:28
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);
}

Кредит для :

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

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

46
1.08.2013 15:46:22
strtolower - не лучший способ сделать регистронезависимыми функции. В некоторых регионах обсадная колонна является более сложной, чем просто верхняя и нижняя.
Sander Rijken 13.05.2009 21:25:33
Я вижу жалобы и никакого решения ... Если вы скажете, что это плохо, то вам следует привести пример того, как это должно быть.
KdgDev 14.05.2009 11:06:48
@WebDevHobo: вот почему я добавил ответ сам за день до вашего комментария. Для вашего кода strcasecmp был действительно правильным решением.
Sander Rijken 6.08.2010 07:34:55

Все ответы до сих пор , кажется, делают кучу ненужной работы, 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;
}
137
4.08.2015 15:13:13
endsWith()Функция имеет ошибку. Его первая строка должна быть (без -1): $expectedPosition = strlen($haystack) - strlen($needle);
Enrico Detoma 5.08.2010 17:16:43
Функция strlen () не является ненужной. Если строка не начинается с указанной иглы, тогда ваш код будет сканировать весь стог сена.
AppleGrew 4.01.2011 15:46:55
@ Отметьте, да, проверка только начала - ОЧЕНЬ быстрее, особенно если вы делаете что-то вроде проверки типов MIME (или любого другого места, где строка должна быть большой)
chacham15 26.09.2011 15:39:56
@mark Я провел несколько тестов с 1000 стогом сена и 10 или 800 иголками, и strpos был на 30% быстрее. Сделайте свои тесты, прежде чем утверждать, что что-то быстрее или нет ...
wdev 6.08.2012 00:39:37
Вы должны серьезно рассмотреть со ссылкой на иглу , как strpos($haystack, "$needle", 0)если есть какой - нибудь шанс , что это не является строкой (например, если это исходит от json_decode()). В противном случае поведение по умолчанию [нечетное] strpos()может привести к неожиданным результатам: « Если игла не является строкой, она преобразуется в целое число и применяется в качестве порядкового значения символа. »
quietmint 3.12.2012 03:47:43

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

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

 function endsWith($needle, $haystack) {
     return preg_match('/' . preg_quote($needle, '/') . '$/', $haystack);
 }
29
16.11.2012 15:14:59
в php для строковых операций порядок параметров равен $ haystack, $ needle. эти функции обращены назад и действуют как функции массива, где порядок на самом деле равен $ needle, $ haystack.
Andy 2.12.2014 01:59:39

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

function startsWith($haystack, $needle, $case=true) {
    if ($case)
        return strncasecmp($haystack, $needle, strlen($needle)) == 0;
    else
        return strncmp($haystack, $needle, strlen($needle)) == 0;
}    
16
17.09.2009 02:50:51
как бы вы покончили с этим?
mpen 26.08.2011 15:20:33
@Mark - вы можете посмотреть на принятый ответ, но я предпочитаю использовать strncmp в основном потому, что считаю его более безопасным.
James Black 26.08.2011 16:45:48
Я имею в виду именно с strncmp. Вы не можете указать смещение. Это будет означать, что вашей функции EndWith придется использовать совершенно другой метод.
mpen 26.08.2011 18:50:26
@Mark - для концов. Я бы просто использовал strrpos ( php.net/manual/en/function.strrpos.php ), но, как правило, всякий раз, когда вы используете strcmp, strncmp, вероятно, более безопасный вариант.
James Black 27.08.2011 00:15:34

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

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 для функции JamesW Black StartSith, потому что strncasecmp на самом деле является нечувствительной к регистру версией strncmp.

2
30.10.2009 00:17:34
Обратите внимание, что strrev()это креативно, но очень дорого, особенно если у вас есть, скажем, 100Kb.
Alexis Wilke 25.06.2014 02:45:54
Используйте ===вместо того, ==чтобы быть уверенным. 0равно многим вещам в PHP.
nawfal 29.01.2016 11:38:58

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

Работает только для строк и если $ 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
23
15.12.2009 08:53:34
это, вероятно, самый эффективный ответ, потому что не использует какую-либо функцию в качестве дополнительной, просто обычную строку ...
user1646111 1.08.2013 10:29:21
Скорее всего, он должен проверить, имеет ли строка хотя бы один символ и поменял ли он два параметра
a1an 15.05.2018 14:51:29
Творческий. Иглы, которые содержат стога сена. Кстати, есть какое-то уродливое угасание:, endsWithChar('','x')но результат верный
Tino 20.07.2018 11:28:16

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

function endsWith($haystack, $needle, $case=true) {
  return preg_match("/.*{$needle}$/" . (($case) ? "" : "i"), $haystack);
}
3
22.12.2010 14:40:13
$ needle должен быть экранирован preg_quote($needle, '/').
Timo Tijhof 16.11.2012 15:10:44

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

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

начинается с () прямо вперед.

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

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

function endsWith($haystack, $needle) {
   return (strpos(strrev($haystack), strrev($needle)) === 0);
}
8
28.06.2011 22:40:33
@FrancescoMM: strpos не "правильный инструмент" ... Почему? Каковы "правильные инструменты" тогда? РЕДАКТИРОВАТЬ: я прочитал ваш ответ ниже. Я думал, что программирование - это как изобретение, использующее ресурсы, которые у вас есть ... Так что нет правильного или неправильного ... только работает или не работает ... производительность вторична.
Fr0zenFyr 24.03.2018 08:22:20
"потому что это инструмент для поиска, а не для сравнения?" Соч. Аристотель
FrancescoMM 24.03.2018 08:42:43

Обновлено 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

243
28.06.2017 19:46:38
Если строки не пусты, как в ваших тестах, это на самом деле как-то (на 20-30%) быстрее: function startswith5b($haystack, $needle) {return ($haystack{0}==$needle{0})?strncmp($haystack, $needle, strlen($needle)) === 0:FALSE;}я добавил ответ ниже.
FrancescoMM 28.07.2013 15:38:33
@Jronny Потому что 110 меньше 133 ... ??
mpen 2.12.2014 16:41:15
Черт, я не знаю, что пришло мне в голову в то время. Полностью отсутствие сна.
Jronny 18.12.2014 03:08:02
@mpen, я вообще не заметил слона :(
Visman 21.11.2017 02:15:28
Эти тесты не годятся для тестирования производительности. То, что вы делаете, использует случайную строку в качестве иглы. В 99,99% случаев совпадения не будет. Большинство функций завершится после сопоставления первого байта. А как насчет случаев, когда совпадение найдено? Какая функция занимает меньше времени, чтобы завершить успешное совпадение? Как насчет случаев, когда 99% иглы совпадают, но не последние несколько байтов? Какая функция занимает наименьшее количество времени, чтобы завершить сопоставление?
Salman A 15.12.2017 15:06:33

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

4
21.02.2012 11:52:55

короче говоря:

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

function endsWith($str, $needle){
   $length = strlen($needle);
   return !$length || substr($str, - $length) === $needle;
}
5
19.04.2012 21:39:24

Вы можете использовать substr_compareфункцию для проверки начала и конца:

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

Это должно быть одним из самых быстрых решений на PHP 7 ( тестовый скрипт ). Проверено на стогах сена 8 КБ, иголках различной длины и полных, частичных и несоответствующих случаях. strncmpэто прикосновение быстрее для начала, но оно не может проверить конец.

1016
24.04.2019 08:24:09
Этот ответ добрался до Daily WTF! : D См. Thedailywtf.com/articles/…
Wim ten Brink 21.04.2016 11:36:45
Обратите внимание, что комментарии @DavidWallace и @FrancescoMM относятся к более старой версии этого ответа. Текущий ответ использует, strrposкоторый (должен) потерпеть неудачу немедленно, если стрелка не соответствует началу стога сена.
Salman A 21.04.2016 14:00:30
Я не понимаю Основано на php.net/manual/en/function.strrpos.php : «Если значение отрицательное, вместо этого поиск будет начинаться с такого количества символов, начиная с конца строки, с обратным поиском». Кажется, это указывает на то, что мы начинаем с символа 0 (из-за -strlength($haystack)) и ищем оттуда назад ? Разве это не значит, что вы ничего не ищете? Я также не понимаю !== falseчасти этого. Я предполагаю, что это опирается на причуду PHP, где некоторые значения являются «правдивыми», а другие «ложными», но как это работает в этом случае?
Welbog 21.04.2016 14:44:10
@Welbog: например, haystack = xxxyyyneedle = yyyи strrposпоиск начинается с первого x. Теперь у нас нет успешного совпадения (найдено x вместо y), и мы больше не можем идти назад (мы находимся в начале строки), поиск немедленно завершается неудачей . Об использовании !== false- strrposв приведенном выше примере будет возвращено 0 или false, а не другое значение. Аналогично, strposв приведенном выше примере может возвращаться $temp(ожидаемая позиция) или false. Я !== falseсогласился, но вы можете использовать === 0и === $tempфункции соответственно.
Salman A 21.04.2016 15:01:15
@ spoo уже было установлено, что strpos === 0 - ужасное решение, если стог сена большой, а иголка не существует.
Salman A 8.10.2016 06:22:13

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

//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 . "!";
}

Вывод:

Нашел значение в начале стоимостного стога!

Имейте в виду, 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 . "!";
}

В этом сценарии нет необходимости использовать функцию launchWith () как

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

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

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

4
12.04.2014 19:17:53
Кажется странным, что если вы ищете "xy" внутри строки "abcdefghijklmxyz" вместо того, чтобы просто сравнивать "x" с "a" и возвращать FALSE, вы просматриваете каждый символ от "a" до "m", а затем в конечном итоге находите "xy" внутри строки, и, наконец, вы возвращаете FALSE, потому что его позиция не равна нулю! Это то, что вы делаете, и это странно и дико, чем любая другая безудержная функция здесь.
FrancescoMM 23.01.2014 15:05:28
Простота в наборе, а не в логике.
Kade Hafen 23.01.2014 17:34:44
Это не столько логика, сколько возможная оптимизация, на которую указывал Франко. Использование strpos()будет медленным, кроме случаев, когда оно совпадает. strncmp()было бы намного лучше в этом случае.
Alexis Wilke 2.07.2014 00:33:26
Когда вы выполняете такие низкоуровневые функции, вы, как правило, хотите выбрать наиболее оптимизированное по скорости решение, независимо от того, насколько оно сложное, поскольку это будет вызываться миллионы раз. Каждая микросекунда, которую вы получаете или теряете, будет иметь реальное значение. Так что лучше избавиться от этого (а затем забыть о сложности, теперь, когда у вас есть функция), вместо того, чтобы искать внешний вид и потерять ужасное количество времени спустя, когда вы даже не знаете, что пошло не так. Представьте себе проверку строки 2 ГБ, которая не совпадает.
dkellner 3.09.2018 13:09:17

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

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

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

4
23.05.2017 12:10:48

Сосредоточив внимание на запуске с, если вы уверены, что строки не пусты, добавление теста на первый символ, перед сравнением, strlen и т. Д. Немного ускоряет процесс:

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

Это как-то (20% -30%) быстрее. Добавление другого теста с символами, такого как $ 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 не выполняет итерацию всей строки (но даже в этом случае), это совсем не удобно.

7
28.07.2013 15:34:42
Там только ускорение, если первые символы разные.
Ja͢ck 2.08.2013 07:51:43
@ Джек, да, конечно, идея в том, что статистически это происходит, поэтому ускорение обычно составляет 20% -30% по всему тестовому набору (включая случаи, когда он не отличается). Вы получаете много, когда они разные, и очень мало, когда нет. В среднем вы получаете 30% (варьируется в зависимости от набора, но в основном вы набираете скорость на больших тестах)
FrancescoMM 18.09.2013 08:42:15
«но это не правильный инструмент для этой работы» ... Любая цитата?
Fr0zenFyr 24.03.2018 08:29:05
WTF. Я перечислил весь процесс ниже, кого я должен процитировать, более того? Вы бы использовали функцию, которая ищет до конца строки, чтобы сказать вам, что первый символ не является «а»? Делай, кого это волнует? Это не правильный инструмент, потому что это инструмент для поиска, а не для сравнения, нет необходимости цитировать Аристотеля, чтобы утверждать очевидное!
FrancescoMM 24.03.2018 08:40:19

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

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

function endsWith($haystack, $needle)
{
    return $needle === '' || substr_compare($haystack, $needle, -strlen($needle)) === 0;
}
18
21.02.2014 02:56:12
+1 Работает с PHP5.1 и ИМХО лучший ответ. Но endsWidthдолжен сделать return $needle==='' || substr_compare(... так что он работает, как и ожидалось, для -strlen($needle)===0которого, без исправления, делает endsWith('a','')возвратfalse
Tino 20.02.2014 21:53:00
@Tino Спасибо ... Я чувствую, что это на substr_compare()самом деле ошибка , поэтому я добавил PR, чтобы исправить это :)
Ja͢ck 21.02.2014 02:55:56
Вызов endsWith('', 'foo')вызывает предупреждение: «substr_compare (): начальная позиция не может превышать начальную длину строки». Может быть, это еще одна ошибка substr_compare(), но чтобы ее избежать, вам нужна предварительная проверка, например ... || (strlen($needle) <= strlen($haystack) && substr_compare(...) === 0);
gx_ 9.08.2015 19:47:18
@ gx_ Не нужно замедляться с большим количеством кода. Просто используйте return $needle === '' || @substr_compare(.., чтобы подавить это предупреждение.
Tino 20.07.2018 11:35:16

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

$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';
6
18.10.2013 13:01:23

Многие из предыдущих ответов будут работать так же хорошо. Тем не менее, это, возможно, так коротко, как вы можете сделать это и сделать то, что вы хотите. Вы просто заявляете, что хотите, чтобы он «вернул истину». Поэтому я включил решения, которые возвращают логическое значение 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';
}
3
27.10.2014 13:03:05
Правда. Однако Питер запрашивал функцию, которая бы работала со строками символов. Тем не менее, я обновил свой ответ, чтобы успокоить вас.
wynshaft 23.10.2014 21:02:56
После редактирования ваше решение теперь полностью устарело. Он возвращает 'true'и в 'false'виде строк, которые оба trueимеют логическое значение. Это хороший пример для чего-то вроде underhanded.xcott.com ;)
Tino 26.10.2014 11:08:17
Ну, Питер только что заявил, что хочет, чтобы это вернуло «правда». Поэтому я решил вернуть то, что он просил. Я добавил обе версии, на случай, если это не то, что он хотел.
wynshaft 27.10.2014 13:04:39

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

     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;
        }
4
7.10.2014 13:27:04
Забыв вернуть false, если он не совпадает. Ошибка неправильная, так как возвращаемое значение функции не должно быть «предположено», но я знаю, что вы собираетесь, по крайней мере, по сравнению с другими ответами.
Spoo 7.10.2016 19:58:19

Я обычно заканчиваю тем, что хожу с библиотекой типа 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   

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

6
23.01.2015 03:53:12

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

$bStartsWith = strpos($sHaystack, $sNeedle) == 0;
$bEndsWith = strrpos($sHaystack, $sNeedle) == strlen($sHaystack)-strlen($sNeedle);
11
29.07.2016 07:11:16
Должны ли вы использовать тройные равные здесь, strpos($sHaystack, $sNeedle) == 0как это strpos($sHaystack, $sNeedle) === 0? Я вижу ошибку, когда false == 0оценивает true.
Kalyan 23.06.2017 14:37:58
$ends_with = strrchr($text, '.'); // Ends with dot
$start_with = (0 === strpos($text, '.')); // Starts with dot
-1
4.11.2017 17:08:41
Согласно документации, strrchr () вернет строку из последнего вхождения '.' до конца, что означает, что ваш $ конец_ будет истинным, если '.' находится где - нибудь в $ тексте. Следовательно, они должны быть следующими: ('.' === strrchr ($ text, '.'))
Sam Bull 5.07.2016 13:20:04
Поскольку ваш ответ неверен и не соответствует заявленным требованиям, а вы отказываетесь принять мои изменения, чтобы исправить свой ответ, я отклоняю этот ответ, поскольку он «опасно неправильный».
Sam Bull 25.03.2017 17:33:37

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

Проверьте, начинается ли строка с «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()), как показано выше.

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

29
30.10.2018 19:55:17
вам не нужно жестко кодировать строку. регулярное выражение может быть динамическим.
Ryan 15.05.2016 03:02:42
@self верно, но если строка не является жестко закодированной, вы должны ее избежать. В настоящее время есть 2 ответа на этот вопрос, которые делают это. Это легко, но немного усложняет код. Поэтому я хотел сказать, что для очень простых случаев, когда возможно жесткое кодирование, вы можете сделать его простым.
noamtm 15.05.2016 19:13:07
Вам также не нужно экранировать косую черту, вы можете заключить регулярное выражение в какой-то другой символ, например @, чтобы /не пришлось экранировать косую черту ( ). Смотрите пример № 3 здесь: php.net/manual/en/function.preg-match.php .
cjbarth 24.10.2018 13:16:28
Спасибо @cjbarth. Изменил мой ответ соответственно. Кстати, «#» - это пример, приведенный в php.net/manual/en/regexp.reference.delimiters.php при работе со слешем .
noamtm 30.10.2018 19:57:03

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

function startsWith($haystack,$needle) {
    if($needle==="") return true;
    if($haystack[0]<>$needle[0]) return false; // ------------------------- speed boost!
    return (0===substr_compare($haystack,$needle,0,strlen($needle)));
}

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

5
2.05.2019 10:27:49
Ошибка в вашем коде: startsWith("123", "0")даетtrue
Tino 20.07.2018 11:10:11
Да, плохо! Произошла проверка. Сожалею! (Просто хотел проиллюстрировать концепцию в строке 3)
dkellner 20.07.2018 14:43:24

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

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

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

6
21.09.2016 14:31:07

Не уверен, почему это так сложно для людей. 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);
}
-3
7.10.2016 19:55:02
Что отличается или новое в вашем ответе по сравнению с ответом MrHus?
Salman A 8.10.2016 06:33:42

Вот безопасная многобайтовая версия принятого ответа, она отлично работает для строк UTF-8:

function startsWith($haystack, $needle)
{
    $length = mb_strlen($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);
}
11
17.04.2019 17:08:38
Я уверен, что это просто трата процессора. все, что вам нужно проверить, для StarstWith и EndsWith, это просто проверить, что байты совпадают, и это именно то, что делает принятый ответ. эта 1 тратит впустую время, вычисляя количество символов иглы utf8, и где положение n-ого символа utf8 стога сена ... я думаю, не будучи уверенным на 100%, это просто пустая трата процессора. Можете ли вы придумать реальный тестовый случай, когда принятый ответ не получается, а это не так?
hanshenrik 12.05.2018 00:06:42
@hanshenrik - это может произойти, между прочим, в очень редком случае, когда вы ищете строку, которая содержит те же байты, что и UTF8, но при этом отсутствует половина последнего символа. Например, у вас есть Unicode C5 91 (буква «ő»), и вы ищете C5 (буква «Å»), он не должен совпадать. С другой стороны, конечно, зачем вам искать в стоге сена utf иглу без утфеля ... Но для пуленепробиваемых проверок это должно считаться возможным.
dkellner 8.09.2018 10:43:11
В startsWithнем должно быть$length = mb_strlen($needle, 'UTF-8');
Thomas Kekeisen 16.04.2019 16:02:05
@ThomasKekeisen Спасибо, исправил это.
Vahid Amiri 17.04.2019 17:08:51

Быстрое решение заканчивается с ():

# 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<br>';
    echo $test.'x endsWith2: '.$result4.' seconds # Accepted answer<br>';
    echo $test.'x endsWith3: '.$result2.' seconds # Second most voted answer<br>';
    echo $test.'x endsWith4: '.$result3.' seconds # Regex answer<br>';
    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
17
24.07.2018 06:29:41
+1 за то, что вы нашли время, чтобы сравнить различные решения и реально сравнить их! Вы также должны указать, какую версию PHP вы использовали, так как оптимизация выполняется по мере развития языка! Я видел существенные улучшения в функциях сравнения строк из одной версии PHP в другую :)
Christophe Deliens 3.10.2018 13:51:06
повторение @ChristopheDeliens и его просьба предоставить версию PHP. Я запустил ваш тест на 7.3.2 и получил аналогичные результаты FWIW.
Jeff 19.02.2019 21:50:08