Видаліть частину рядка після певного символу


144

Мені просто цікаво, як я міг видалити все після певної підрядки в PHP

колишній:

Posted On April 6th By Some Dude

Мені б хотілося, щоб він видалив увесь текст, включаючи і після, підряд рядок "За"

Дякую


1
Що робити, якщо підрядний ряд відбувається двічі (або більше)?
Барт Кіерс

18
Як зауваження, якщо ви це робите, щоб ви могли взяти чужий вміст і представити його на своєму сайті, не варто .
ceejayoz

Я згоден з ceejayoz. Це дуже схоже на те, що ви намагаєтесь використовувати вміст, до якого ви дійсно не маєте доступу, і ви намагаєтесь видалити будь-яку посилання на оригінального автора. Це було б не дуже приємно ...
selfawaresoup

2
Альтернативне чудове рішення stackoverflow.com/a/9315908/1518921 :)
Guilherme Nascimento

1
Насправді звичайно потрібно робити такі речі з законних причин під час роботи зі вмістом, створеним CMS. Причина в тому, що ви ніколи не хочете возитися з фактичним кодом, який створює подібний фрагмент, тому що ви порушите свої оновлення; так, ви даєте йому зробити свою справу, тоді ви робите свою справу.
Nosajimiki

Відповіді:


292
$variable = substr($variable, 0, strpos($variable, "By"));

Простий англійською мовою: дайте мені частину рядка, починаючи з початку і закінчуючи на тому місці, де ви вперше стикаєтеся з роздільником.


11
А як щодо "робити це лише тоді, коли існує" від "?
Аліссо

3
Ти маєш рацію. strpos поверне FALSE, якщо "By" не буде знайдено. substr поверне порожній рядок, якщо вказана довжина помилкова. На практиці, ймовірно, було б корисно перевірити, чи існує "By", а потім робити це лише в тому випадку, якщо це так (інакше просто залишити рядок в спокої).
Остін Фіцпатрік

13
Це працює: strpos ($ змінна, "За")? substr ($ змінна, 0, strpos ($ змінна, "За")): $ змінна;
Ной Гарі

Я ставлю відповідь, яка, на мою думку, стосується всього нижче, а також пояснюю способи поводження з усіма різними речами, такими як нечутливі до регістру, множинні випадки та регулярні вирази. Якщо хтось хоче зробити щось гнучкіше або не має контролю над вхідними даними, можливо, варто перевірити.
azoundria

1
Мені ідеально підходить @Goahnary!
деніс

106

Якщо ви використовуєте PHP 5.3+, подивіться прапор $ before_needle з strstr ()

$s = 'Posted On April 6th By Some Dude';
echo strstr($s, 'By', true);

4
Дякую, це справді правильна відповідь сьогодні !
Матмарбон

59
Зауважте, що він повернеться, FALSEякщо частина рядка не буде знайдена. Таким рішенням може бути:echo strstr($s, 'By', true) ?: $s;
kenorb

6
Відповідь kenorb повинна бути прийнятою сьогодні. Іншою альтернативою може стати explode(' By', $s)[0]ІМХО квадратних канді
Зак Морріс

Дійсно, перевірка існування kenorb - це спосіб це зробити, навіть не вимагаючи тестування рядка.
BarryMode

Тут просто сказати метод @ kenorb - це синиці.
Квінн Комендант,

32

Як щодо використання explode:

$input = 'Posted On April 6th By Some Dude';
$result = explode(' By',$input);
return $result[0];

Переваги:


@bkac - Що не так у старомодному, якщо він працює і не знецінюється?
squarecandy

3
Це виключає додаткову перевірку наявності рядка роздільника, необхідного прийнятою відповіддю.
Девід Каллен

17

Ви можете зробити:

$posted = preg_replace('/ By.*/', '', $posted);
echo $posted;

4
+1 Це єдиний, хто працює, якщо контрольні символи НЕ присутні (на відміну від інших, які повертають порожню рядок, якщо контрольних символів немає у вихідному рядку)
Том Ожер,

9

Одним із методів буде:

$str = 'Posted On April 6th By Some Dude';
echo strtok($str, 'By'); // Posted On April 6th

Це найкраща відповідь, яка працює, навіть якщо By немає в рядку, відповідь substr неправильна, тому що існує, якщо існує, це не вдається.
neoteknic

Це неправильно: функція не розділиться Byза будь-яким символом у другому параметрі. Значить, він розділиться на Bабо y. Технічно це не отримує все до By.
msb

Будьте уважні: strtok поверне частину рядка після символу, якщо це перший символ у рядку, наприклад, strtok('a:b', ':')повернеться, aале strtok(':b', ':')повернеться b, а не порожній рядок, як ви очікували.
Куінн Комендант

6

Спробуйте це.

function strip_after_string($str,$char)
    {
        $pos=strpos($str,$char);    
        if ($pos!==false) 
        {
            //$char was found, so return everything up to it.
            return substr($str,0,$pos);
        } 
        else 
        {
            //this will return the original string if $char is not found.  if you wish to return a blank string when not found, just change $str to ''
            return $str; 
        }
    }

Використання:

<?php
    //returns Apples
    $clean_string= strip_after_string ("Apples, Oranges, Banannas",",");
?>

Вам було б набагато краще назвати функцію strip_after_string замість sas та мати кодову базу, наповнену криптовалютами. Це моя улюблена найбільш читана відповідь на це питання.
Антер

5

Відповідь Остіна працює для вашого прикладу.

Більш загально, вам було б добре вивчити функції регулярного вираження коли підряд, на який ви розщеплюєте, може відрізнятися між рядками:

$ змінний = preg_replace ('/ За. * /', '', $ змінна);

+1, це правильно. Якщо ви хочете також розділити на "Автор:" або "Написав:" Або "Використовується за згодою:", мабуть, було б найпростіше зробити регулярний вираз. Коли я не виконую жодної логіки регулярного вираження, я схильний уникати їх, оскільки вони, схоже, негайно додають рівень складності коду (принаймні для мене)
Остін Фіцпатрік

4

Ви можете використовувати listі explodeфункції:

list($result) = explode("By", "Posted On April 6th By Some Dude", 2);
// $result is "Posted On April 6th "

Це найточніше. Як би я хотів, щоб я міг проголосувати за це двічі
Джон Макс



2

Використовуючи регулярний вираз: $string = preg_replace('/\s+By.*$/', '', $string)


Будь ласка, додайте пояснення до цієї відповіді лише для коду.
mickmackusa

2

Нижче є найбільш ефективним методом (за часом виконання) , щоб відрізати всі після першої By в рядку. Якщо By не існує, повертається повна рядок. Результат - в $ sResult.

$sInputString = "Posted On April 6th By Some Dude";
$sControl = "By";

//Get Position Of 'By'
$iPosition = strpos($sInputString, " ".$sControl);
if ($iPosition !== false)
  //Cut Off If String Exists
  $sResult = substr($sInputString, 0, $iPosition);
else
  //Deal With String Not Found
  $sResult = $sInputString;

//$sResult = "Posted On April 6th"

Якщо ви не хочете бути чутливими до регістру, використовуйте стрипоси замість стріпових. Якщо ви думаєте, що By може існувати не один раз і хочете вирізати все після останнього появи, використовуйте strrpos .

Нижче представлений менш ефективний метод, але він займає менше місця в коді. Цей метод також є більш гнучким і дозволяє виконувати будь-які регулярні вирази.

$sInputString = "Posted On April 6th By Some Dude";
$pControl = "By";

$sResult = preg_replace("' ".$pControl.".*'s", '', $sInputString);

//$sResult = "Posted On April 6th"

Наприклад, якщо ви хотіли видалити все після дня:

$sInputString = "Posted On April 6th By Some Dude";
$pControl = "[0-9]{1,2}[a-z]{2}"; //1 or 2 numbers followed by 2 lowercase letters.

$sResult = preg_replace("' ".$pControl.".*'s", '', $sInputString);

//$sResult = "Posted On April"

Для нечутливих до регістру додавайте модифікатор i таким чином:

$sResult = preg_replace("' ".$pControl.".*'si", '', $sInputString);

Для того, щоб отримати все , що за останній By , якщо ви думаєте , що може бути більше , ніж один, додати додатковий * на початку , як це .:

$sResult = preg_replace("'.* ".$pControl.".*'si", '', $sInputString);

Але тут також є дійсно потужний спосіб, за допомогою якого ви можете використовувати preg_match, щоб робити те, що ви можете намагатися зробити:

$sInputString = "Posted On April 6th By Some Dude";

$pPattern = "'Posted On (.*?) By (.*?)'s";
if (preg_match($pPattern, $sInputString, $aMatch)) {
  //Deal With Match
  //$aMatch[1] = "April 6th"
  //$aMatch[2] = "Some Dude"
} else {
  //No Match Found
}

Регулярні вирази можуть здатися заплутаними спочатку, але вони можуть бути дуже потужними, і ваш найкращий друг, коли ви їх освоїте! Удачі!


1

Чому ...

Це, ймовірно, надмірне значення для потреб більшості людей, але це стосується ряду речей, на які кожна окрема відповідь вище не відповідає. З предметів, на які він звертається, три з них були потрібні для моїх потреб. При чіткій дужці та відмовленні від коментарів це все ще може бути читабельним лише на 13 рядках коду.

Це стосується наступних питань:

  • Вплив на ефективність використання REGEX vs strrpos / strstr / strripos / stristr.
  • Використання strripos / strrpos, коли символ / рядок не знайдено в рядку.
  • Видалення з лівого або правого боку рядка (перший або останній випадок).
  • CaSe чутливість.
  • Бажаючи можливість повернути початковий рядок без змін, якщо пошук / рядок пошуку не знайдено.

Використання:

Надішліть початковий рядок, рядок пошуку / рядок, "R" / "L" для початку з правого або лівого боку, істинного / помилкового для чутливості регістру. Наприклад, пошукайте "тут" нечутливі регістри, в рядку, почніть праворуч.

echo TruncStringAfterString("Now Here Are Some Words Here Now","here","R",false);

Вихід буде "Тепер ось деякі слова". Якщо змінити "R" на "L", вийде: "Зараз".

Ось функція:

function TruncStringAfterString($origString,$truncChar,$startSide,$caseSensitive)
{
    if ($caseSensitive==true && strstr($origString,$truncChar)!==false)
    {
        // IF START RIGHT SIDE:
        if (strtoupper($startSide)=="R" || $startSide==false)
        {   // Found, strip off all chars from truncChar to end
            return substr($origString,0,strrpos($origString,$truncChar));
        }

        // IF START LEFT SIDE: 
        elseif (strtoupper($startSide)=="L" || $startSide="" || $startSide==true)
        {   // Found, strip off all chars from truncChar to end
            return strstr($origString,$truncChar,true);
        }           
    }
    elseif ($caseSensitive==false && stristr($origString,$truncChar)!==false)
    {           
        // IF START RIGHT SIDE: 
        if (strtoupper($startSide)=="R" || $startSide==false)
        {   // Found, strip off all chars from truncChar to end
            return substr($origString,0,strripos($origString,$truncChar));
        }

        // IF START LEFT SIDE: 
        elseif (strtoupper($startSide)=="L" || $startSide="" || $startSide==true)
        {   // Found, strip off all chars from truncChar to end
            return stristr($origString,$truncChar,true);
        }
    }       
    else
    {   // NOT found - return origString untouched
        return $origString;     // Nothing to do here
    }           

}

Якщо ви спростуєте мою робочу відповідь, було б вдячно, ви сказали, чому.
Роберт Мауро

0

Використовуйте функцію strstr .

<?php
$myString = "Posted On April 6th By Some Dude";
$result = strstr($myString, 'By', true);

echo $result ;

Третій параметр trueповідомляє функцію повертати все до першого появи другого параметра.


1
strtok($str, 'By')виглядає простіше
mu3

-2
$variable = substr($initial, 0, strpos($initial, "By"));

if (!empty($variable)) { echo $variable; } else { echo $initial; }
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.