PHP извлечение подстроки. Получить строку перед первой '/' или всей строкой


170

Я пытаюсь извлечь подстроку. Мне нужна помощь с этим в PHP.

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

home/cat1/subcat2 => home

test/cat2 => test

startpage => startpage

Я хочу получить строку до первого /, но если нет /, получить всю строку.

Я попытался,

substr($mystring, 0, strpos($mystring, '/'))

Я думаю, что это говорит - получить позицию /и затем получить подстроку из позиции 0 в эту позицию.

Я не знаю, как справиться со случаем, когда нет /, не делая заявление слишком большим.

Есть ли способ справиться с этим делом, не делая оператор PHP слишком сложным?


1
Вы могли бы найти s($str)->beforeFirst('/')полезным, как найти в этой автономной библиотеке .
кар

Ответы:


261

использование explode()

$arr = explode("/", $string, 2);
$first = $arr[0];

В этом случае я использую limitпараметр to, explodeчтобы php не сканировал строку больше, чем нужно.


2
+1 Спасибо за ответ. Сработало :) Но один вопрос. Я могу только сделать это -> $arr = explode('/',$mystring,2); echo $arr[0];. Я не могу получить первую строку в одном операторе - echo explode('/',$mystring,2)[0];. Так как Explode возвращает массив, я должен быть в состоянии сделать это правильно? Но я получаю ошибку. Какие-либо предложения?

1
Php не любит, когда вы индексируете возвращаемые значения из функций.
gnud

3
ой. Ладно. было бы неплохо, если бы это было возможно.

36
explode() + [0]это многословный способ написатьstrtok($string, "/")
Марио

5
Кстати, вы можете взорвать ("/", $ string, 2) [0] в php 5.5
billynoah

293

Наиболее эффективным решением является strtokфункция:

strtok($mystring, '/')

Например:

$mystring = 'home/cat1/subcat2/';
$first = strtok($mystring, '/');
echo $first; // home

и

$mystring = 'home';
$first = strtok($mystring, '/');
echo $first; // home

25
Это также примерно на 40% быстрее, чем current-explodeрешение. (Не то, чтобы я использовал его так часто, чтобы это
имело

5
Это элегантно и быстро - должен быть принят ответ.
Коста Контос

5
Это должен быть исключенный ответ. Определенно быстрее и больше циклов памяти и процессора эффективнее, чем любое из приведенных explodeрешений.
Шивам Махешвари

Проблема с strtokIS first/secondвернется , firstно /secondвернется , secondа не пустая строка.
rybo111 27.09.16

В дополнение к моему вышеупомянутому комментарию: поведение, когда пустая часть была найдена, изменилось с PHP 4.1.0. Старое поведение вернуло пустую строку, а новое правильное поведение просто пропускает часть строки
rybo111

95
$first = explode("/", $string)[0];

2
элегантно, но не очень эффективно в компьютерное время. Но в наши дни люди больше не заботятся о минутных циклах процессора
Деннис

13

Как насчет этого :

substr($mystring.'/', 0, strpos($mystring, '/'))

Просто добавьте «/» в конец mystring, чтобы быть уверенным, что есть хотя бы один;)


Вы можете просто проверить, есть ли одна косая черта в строке, прежде чем делать это. Во всяком случае, это самое простое решение.
Гильерме Сампайо

12

Однострочная версия принятого ответа:

$out=explode("/", $mystring, 2)[0];

Должен работать в php 5.4+


1
В отличие от приведенного ниже, «2» ограничивает количество создаваемых им элементов массива. Хорошая мысль.
Бен в CA

9

Это, наверное, самый короткий пример, который мне пришёл в голову:

list($first) = explode("/", $mystring);

1) list()будет автоматически назначать строку до тех пор, пока "/"разделитель не будет найден
2) если разделитель "/"не найден, тогда будет назначена вся строка

... и если вы действительно одержимы производительностью, вы можете добавить дополнительный параметр для разнесения, explode("/", $mystring, 2)который ограничивает максимум возвращаемых элементов.


2
Мне нравится этот подход. Сохраняет создание ненужного массива. И strtok()небезопасно.
rybo111

1
@ rybo111: Что небезопасно strtok()?
Хакре

@ rybo111 Я повторяю мнение Хакре; что делает strtok()небезопасным?
Доктор J

@hakre Посмотри мои ответы на ответ jmarceli. Это может вызвать неожиданное поведение в зависимости от версии PHP.
rybo111

PHP 4.1.0 - Rly?
Хакре

8

Лучше поздно, чем никогда. PHP имеет предопределенную функцию для этого. вот этот хороший способ.

strstr

если вы хотите получить деталь перед совпадением, просто установите before_needle (третий параметр) на true http://php.net/manual/en/function.strstr.php

function not_strtok($string, $delimiter)
{    
    $buffer = strstr($string, $delimiter, true);

    if (false === $buffer) {
        return $string;
    }

    return $buffer;
}

var_dump(
    not_strtok('st/art/page', '/')
);

Это не безопасно использовать, если вы не можете быть уверены, что игла существует в веревке.
частота

@fooquency - True, но вы всегда можете добавить символ в конец проверяемой строки, просто чтобы быть уверенным.
Майк Шинкель

Спасибо. Мои тесты показали, что strstrэто немного быстрее, чем strtok. Я пойду с первым.
Ян Ян

5

Функция strstr () в PHP 5.3 должна делать эту работу. Однако третий параметр должен быть установлен в true.

Но если вы не используете 5.3, то приведенная ниже функция должна работать точно:

function strbstr( $str, $char, $start=0 ){
    if ( isset($str[ $start ]) && $str[$start]!=$char ){
        return $str[$start].strbstr( $str, $char, $start+1 );
    }
}

Я не проверял это, хотя, но это должно работать просто отлично .. И это также довольно быстро


3
+1 за strstr(), но имейте в falseвиду, что он возвращает, если строка не содержит $needle, поэтому приведенные explode()выше решения лучше подходят в этом случае.
Бенджамин

3

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

/**
 * Return string before needle if it exists.
 *
 * @param string $str
 * @param mixed $needle
 * @return string
 */
function str_before($str, $needle)
{
    $pos = strpos($str, $needle);

    return ($pos !== false) ? substr($str, 0, $pos) : $str;
}

Вот пример использования:

$sing = 'My name is Luka. I live on the second floor.';

echo str_before($sing, '.'); // My name is Luka

3

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

$s = preg_replace('|/.*$|', '', $s);

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


2
Regex, вероятно, тоже излишний, но, поскольку я говорю то же самое, explodeбыло бы интересно посмотреть, что быстрее.
rvighne

1
в этом нет абсолютно ничего плохого, и я не могу понять, почему это заслуживает 2 отрицательных голосов. Лично я бы не использовал регулярные выражения, но это определенно не так.
Биллиноа

2

Использование currenton explodeоблегчит процесс.

 $str = current(explode("/", $str, 2));

0
$string="kalion/home/public_html";

$newstring=( stristr($string,"/")==FALSE ) ? $string : substr($string,0,stripos($string,"/"));

0

Вы также можете использовать это однострочное решение

list($substring) = explode("/", $string);

-1

Я думаю, что это должно работать?

substr($mystring, 0, (($pos = (strpos($mystring, '/') !== false)) ? $pos : strlen($mystring)));

Ваша функция всегда будет возвращать первый символ, потому что вы делаете (strpos ($ mystring, '/')! == false) перед тем, как назначить его в $ pos, вам нужно сделать (($ pos = strpos ($ firstColumnName, '_'))! == неверно). Это будет тот лайнер, который ищет тот, кто разместил вопрос.
Михай П.

-1

почему бы не использовать:

function getwhatiwant($s)
{
    $delimiter='/';
    $x=strstr($s,$delimiter,true);
    return ($x?$x:$s);
}

ИЛИ:

   function getwhatiwant($s)
   {
       $delimiter='/';
       $t=explode($delimiter, $s);
       return ($t[1]?$t[0]:$s);
   }
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.