Вилучення підрядок 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параметр, щоб explodephp не сканував рядок більше, ніж потрібно.


2
+1 Дякую за відповідь. Це спрацювало :) Але одне питання. Я лише в змозі це зробити -> $arr = explode('/',$mystring,2); echo $arr[0];. Я не в змозі отримати перший рядок в одному самому операторі - echo explode('/',$mystring,2)[0];. Оскільки explode повертає масив, я повинен мати можливість це зробити правильно? Але я отримую помилку. Будь-які пропозиції?

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

3
ой. добре. було б добре, якби це було можливо.

36
explode() + [0]це довгодушний спосіб писатиstrtok($string, "/")
mario

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рішення. (Не те, що я використовую його так часто, що має значення.)
towr

5
Це елегантно і швидко - повинна бути прийнята відповідь.
Коста Контос

5
Це має бути виключена відповідь. Однозначно більш швидкі та більш ефективні цикли пам'яті та процесора, ніж будь-яке із explodeзаданих рішень.
Шивам Махешварі

Проблема з strtokє first/secondповернеться, firstале /secondповернеться, secondа не порожній рядок.
rybo111

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

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

2
елегантний, але не дуже ефективний у комп’ютерний час. Але в ці дні люди вже більше не переймаються хвилиновими циклами процесора
Денніс

13

Як що до цього :

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

Просто додайте "/" до кінця містінгу, щоб ви могли бути впевнені, що принаймні є;)


Ви можете просто перевірити, чи є одна коса риса в рядку, перш ніж робити це. У всякому разі, це найпростіше рішення.
Гільгерме Сампайо

12

Однорядкова версія прийнятої відповіді:

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

Має працювати в php 5.4+


1
На відміну від наведеного нижче, "2" обмежує кількість створених ним масивів. Гарне мислення.
Бен в Каліфорнії

9

Це, мабуть, найкоротший приклад, який прийшов мені в голову:

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

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

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


2
Мені подобається такий підхід. Економить створення зайвого масиву. І strtok()небезпечно.
rybo111

1
@ rybo111: Що таке небезпечне strtok()?
хакре

@ rybo111 Я повторюю почуття хакре; що робить strtok()небезпечним?
Doktor J

@hakre Дивіться мої відповіді на відповідь jmarceli. Це може спричинити несподівану поведінку залежно від версії PHP.
rybo111

php 4.1.0 - rly?
хакре

8

Пізно краще, ніж ніколи. php має заздалегідь задану функцію для цього. ось такий хороший шлях.

strstr

якщо ви хочете отримати частину перед матчем, просто встановіть перед_needle (3-й параметр) на 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

@fooquency - Це правда, але ви завжди можете додати символу до кінця рядка, який ви перевіряєте, просто щоб бути впевненим.
MikeSchinkel

Дякую. Мої тести показали, що 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 for 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 голосів. Я особисто не використовував би регулярний вираз, але це, звичайно, не так.
billynoah


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 = strpos ($ firstColumnName, '_'))! == false). Це був би 1 лайнер, якого шукає хлопець, який розмістив запитання.
Михай П. П.

-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.