php strtok не работает, если разделитель является первым символом в строке?

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

$href = "test#content";
$href = strtok($href,'#');
echo $href;

выходы:

test

Я столкнулся с проблемой, когда строка начинается с разделителя:

$href = "#content";
$href = strtok($href,'#');
echo $href;

Вместо желаемого вывода '' он выводит:

content

Почему это работает не так, как в первом примере, и как наиболее эффективно получить желаемые результаты с наименьшим количеством лишнего кода?


person Acidon    schedule 30.11.2015    source источник
comment
В мануале написано The behavior when an empty part was found changed with PHP 4.1.0. The old behavior returned an empty string, while the new, correct, behavior simply skips the part of the string:   -  person Professor Abronsius    schedule 30.11.2015
comment
На самом деле это происходит из-за фундаментального непонимания того, что на самом деле делает strtok(), и предположения, что это какой-то вариант взрыва(), который просто возвращает результаты по одному за раз.   -  person Mark Baker    schedule 30.11.2015
comment
Почему игнорирование пустых строк является правильным поведением? Я могу вспомнить много случаев, когда это то, что вы хотели бы, чтобы strtok делал. Почему команда PHP просто не добавила флаг или директиву PHP, чтобы указать, какое поведение нужно программисту?   -  person David Spector    schedule 07.01.2020


Ответы (5)


В этом случае вы можете использовать strstr() для возврата левой части разделителя , при передаче третьего ($before_needle) аргумента по умолчанию возвращается правильный сайт. Чтобы проверить, существует ли разделитель, вы можете использовать preg_match(). чтобы выполнить задачу, выполняется регулярное выражение, возвращающее true, если шаблон найден или false в случае неудачи.

$href = "test#content";

if(preg_match('/#/', $href)){
    echo strstr($href, '#', true); //test
}else{
    echo 'delimiter not found';
}
person rray    schedule 30.11.2015
comment
Работает до тех пор, пока строка содержит '#', иначе возвращает пустую строку. Не могу использовать, так как только некоторые из моих строк содержат '#' . - person Acidon; 30.11.2015
comment
@Acidon, там нет разделителя исправлений? - person rray; 30.11.2015
comment
правильно, некоторые строки содержат разделители и должны быть обработаны, другие нет и должны быть оставлены как есть. - person Acidon; 30.11.2015
comment
@acidon, тогда почему ты не упомянул об этом в своем вопросе? - person Jamie Harding; 30.11.2015
comment
Может быть, потому что при использовании strtok он не возвращал пустых результатов, если разделитель отсутствовал, и я надеялся пойти по пути strtok и думал, что использую его неправильно? В любом случае, я пошел по вашему пути, добавив условную проверку, if (strpos($href, "#") !== false) { $href = strstr($href, '#', true); }, я отредактирую свой вопрос, и если вы обновите свой ответ, я приму его. - person Acidon; 30.11.2015
comment
Preg_match медленнее и имеет чуть более сложный интерфейс по сравнению со strtok. Почему strtok не может возвращать пустые строки? - person David Spector; 07.01.2020

Если вы хотите вернуть все до «#», вы можете использовать взорвать.

Поведение при обнаружении пустой части изменилось в PHP 4.1.0. Старое поведение возвращало пустую строку, а новое, правильное поведение просто пропускало часть строки.

ТЕСТ 1 (https://3v4l.org/4lP5u):

$href = "#content";
$href = explode('#', $href);
echo $href['0'];

//returns ''

ТЕСТ 2 (https://3v4l.org/ov9Yl):

$href = "test#content";
$href = explode('#', $href);
echo $href['0'];

//returns 'test'

ИЗМЕНИТЬ:

Ой, я добавил неправильную ссылку в примере TEST 2, теперь обновил ссылку.

Согласно вашему комментарию

к сожалению, я не могу взорвать маршрут, так как переменная $href будет повторно использована позже и не может быть массивом. Кроме того, в примере по вашей второй ссылке есть неправильный вывод, потому что он повторяет $href['1'] вместо $href['0']

ты мог бы:

ТЕСТ 3 (https://3v4l.org/uWPOk):

$href = "test#content";
$href = explode('#', $href);
$href = $href['0'];
echo $href;

ТЕСТ 4 (https://3v4l.org/rtIJ0):

Это проверяет, содержит ли строка #, и разрывает ее, иначе $href остается прежним.

$href = "test#content";

if (strpos($href, '#') !== FALSE){
    $href = explode('#', $href);
    $href = $href['0'];
    echo $href;
}else{
    echo "$href";
}
person Jamie Harding    schedule 30.11.2015
comment
к сожалению, я не могу развернуть маршрут, так как переменная $href будет повторно использоваться позже и не может быть массивом. Кроме того, в примере по вашей второй ссылке есть неправильный вывод, потому что он повторяет $href['1'] вместо $href['0'] . - person Acidon; 30.11.2015
comment
@Acidon Плохо, я добавил неправильную ссылку. С тех пор я обновил его и добавил новый тест. - person Jamie Harding; 30.11.2015
comment
Почему strtok не может возвращать пустые строки? - person David Spector; 07.01.2020

Возможно, preg_split может быть полезен в этой ситуации:

$href = "#content";
$pieces=preg_split('@#@',$href);
echo $pieces[0];/* Empty */
echo $pieces[1];/*content*/
person Professor Abronsius    schedule 30.11.2015


если вам нужна строка перед #, вы должны использовать explode. Обходной путь для вашего подхода может быть примерно таким:

<?php 
$href = "#content";
if($href[0]=='#'){//check the first index character
    $href="''".$href;
}
$href = strtok($href,'#');
echo $href;

?>
person Suchit kumar    schedule 30.11.2015