Usuń część ciągu po określonym znaku

144

Zastanawiam się tylko, jak mogę usunąć wszystko po pewnym podciągu w PHP

dawny:

Posted On April 6th By Some Dude

Chciałbym, aby usuwał cały tekst, w tym podłańcuch „By” i po nim

Dzięki

Belgin Fish
źródło
1
Co się stanie, jeśli podciąg wystąpi dwukrotnie (lub więcej)?
Bart Kiers
18
Uwaga: jeśli robisz to, aby móc zabrać czyjąś zawartość i zaprezentować ją na własnej stronie, nie rób tego .
ceejayoz
Zgadzam się z ceejayoz. To brzmi bardzo tak, jakbyś próbował użyć treści, do której tak naprawdę nie masz dostępu, i próbujesz usunąć wszelkie odniesienia do oryginalnego autora. To nie byłoby zbyt miłe ...
selfawaresoup
2
Alternatywne świetne rozwiązanie stackoverflow.com/a/9315908/1518921 :)
Guilherme Nascimento
1
Podczas pracy z treścią generowaną przez CMS często trzeba robić tego typu rzeczy z uzasadnionych powodów. Powodem jest to, że nigdy nie chcesz zadzierać z rzeczywistym kodem, który tworzy taki fragment kodu, ponieważ będziesz przerywać aktualizacje; więc pozwalasz mu robić swoje, a potem robisz swoje.
Nosajimiki

Odpowiedzi:

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

Mówiąc prostym językiem: podaj mi część ciągu zaczynającą się od początku i kończącą się w miejscu, w którym po raz pierwszy napotkasz separator.

Austin Fitzpatrick
źródło
11
A co z „rób to tylko wtedy, gdy„ przez ”istnieje?
Alisso,
3
Masz rację. strpos zwróci FALSE, jeśli „By” nie zostanie znalezione. substr zwróci pusty ciąg, jeśli podana długość jest fałszywa. W praktyce prawdopodobnie przydatne byłoby sprawdzenie, czy istnieje „By”, a następnie zrobienie tego tylko wtedy, gdy tak jest (w przeciwnym razie pozostawienie samego ciągu).
Austin Fitzpatrick
13
To działa: strpos (zmienna $, „By”)? substr (zmienna $, 0, strpos (zmienna $, "wg")): $ zmienna;
Noah Gary
Umieściłem odpowiedź, która moim zdaniem odnosi się do wszystkiego poniżej, a także wyjaśnia sposoby radzenia sobie z różnymi rzeczami, takimi jak niewrażliwość na wielkość liter, wielokrotne wystąpienia i wyrażenia regularne. Jeśli ktoś chce zrobić coś bardziej elastycznego lub nie ma kontroli nad wprowadzanymi danymi wejściowymi, prawdopodobnie warto to sprawdzić.
azoundria
1
Działa idealnie dla mnie @Goahnary!
denis
106

Jeśli używasz PHP 5.3+, spójrz na flagę $ before_needle funkcji strstr ()

$s = 'Posted On April 6th By Some Dude';
echo strstr($s, 'By', true);
VolkerK
źródło
4
Dzięki, to jest obecnie właściwa odpowiedź !
Matmarbon
59
Zwróć uwagę, że zwróci, FALSEjeśli część ciągu nie zostanie znaleziona. Tak więc rozwiązaniem mogłoby być:echo strstr($s, 'By', true) ?: $s;
kenorb
6
^^^ Odpowiedź kenorb powinna być dzisiaj zaakceptowana. Inną alternatywą byłoby explode(' By', $s)[0]IMHO Squarecandy
Zack Morris
Rzeczywiście, sprawdzanie istnienia kenorb jest sposobem na to, nawet jeśli nie jest to wymagane do testowania łańcucha.
BarryMode
Tutaj, aby powiedzieć, metodą @ kenorb są cycki.
Quinn Comendant
32

Co powiesz na używanie explode:

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

Zalety:

squarecandy
źródło
@bkac - Co jest nie tak ze staroświeckim, o ile działa i nie jest amortyzowany?
squarecandy
3
Eliminuje to dodatkowe sprawdzanie istnienia łańcucha ogranicznika wymaganego przez zaakceptowaną odpowiedź.
David Cullen
17

Mógłbyś:

$posted = preg_replace('/ By.*/', '', $posted);
echo $posted;
JYelton
źródło
4
+1 To jedyny, który działa, jeśli znaki kontrolne NIE są obecne (w przeciwieństwie do innych, które zwracają pusty ciąg, jeśli znaki kontrolne nie są obecne w ciągu źródłowym)
Tom Auger
9

Jedną z metod byłoby:

$str = 'Posted On April 6th By Some Dude';
echo strtok($str, 'By'); // Posted On April 6th
HADI
źródło
Jest to najlepsza odpowiedź, która działa, nawet jeśli By nie ma w ciągu, odpowiedź substr jest błędna, ponieważ jest przez doest'nt exist i nie powiedzie się.
neoteknic
To jest niepoprawne: funkcja nie będzie dzielona według By, ale według dowolnego znaku w drugim parametrze. Oznacza to, że zostanie podzielony na jeden Blub y. Technicznie rzecz biorąc, nie uzyskuje się wszystkiego przed By.
msb
Bądź ostrożny: strtok zwraca część łańcucha po znaku, jeżeli jest to pierwszy znak w ciągu np strtok('a:b', ':')powróci aale strtok(':b', ':')wróci b, nie pusty ciąg jak można się spodziewać.
Quinn Comendant
6

Spróbuj tego.

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; 
        }
    }

Stosowanie:

<?php
    //returns Apples
    $clean_string= strip_after_string ("Apples, Oranges, Banannas",",");
?>
Tim Yobson
źródło
Znacznie lepiej byłoby nazwać funkcję strip_after_string zamiast sas i mieć bazę kodu pełną tajemniczych inicjalizacji. Jest to jednak moja ulubiona i najbardziej czytelna odpowiedź na to pytanie.
Anther
5

Odpowiedź Austina działa w twoim przykładowym przypadku.

Mówiąc bardziej ogólnie, dobrze byłoby przyjrzeć się funkcjom wyrażeń regularnych, gdy podciąg, na którym dzielisz, może różnić się między łańcuchami:

$ zmienna = preg_replace ('/ By. * /', '', $ zmienna);
jemfinch
źródło
+1, to prawda. Gdybyś chciał podzielić na „Autor:” lub „Autor:” lub „Użyte za zgodą:”, prawdopodobnie najłatwiej byłoby zrobić wyrażenie regularne. Kiedy jednak nie stosuję żadnej logiki wyrażeń regularnych, staram się ich unikać, ponieważ wydają się one natychmiast dodawać poziom złożoności do kodu (przynajmniej dla mnie)
Austin Fitzpatrick,
4

Możesz używać listi explodefunkcji:

list($result) = explode("By", "Posted On April 6th By Some Dude", 2);
// $result is "Posted On April 6th "
Salman A
źródło
To jest najdokładniejsze. Chciałbym móc głosować na to dwa razy
John Max
4
$var = "Posted On April 6th By Some Dude";
$new_var = substr($var, 0, strpos($var, " By"));
Tim Cooper
źródło
2

preg_replace oferuje w jedną stronę:

$newText = preg_replace('/\bBy.*$/', '', $text);
poza
źródło
2

Używając wyrażenia regularnego: $string = preg_replace('/\s+By.*$/', '', $string)

Ming-Tang
źródło
Prosimy o dołączenie wyjaśnień do odpowiedzi zawierającej tylko kod.
mickmackusa,
2

Poniżej znajduje się najbardziej wydajna metoda (według czasu wykonywania) odcinania wszystkiego po pierwszym By w ciągu. Jeśli By nie istnieje, zwracany jest pełny ciąg. Wynik jest w $ 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"

Jeśli nie chcesz uwzględniać wielkości liter, użyj stripos zamiast strpos. Jeśli uważasz, że By może istnieć więcej niż raz i chcesz wyciąć wszystko po ostatnim wystąpieniu, użyj strrpos .

Poniżej znajduje się mniej wydajna metoda, ale zajmuje mniej miejsca na kod. Ta metoda jest również bardziej elastyczna i umożliwia wykonanie dowolnego wyrażenia regularnego.

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

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

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

Na przykład, jeśli chcesz usunąć wszystko po dniu:

$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"

Aby nie rozróżniać wielkości liter, dodaj modyfikator i w następujący sposób:

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

Aby dostać wszystko za ostatnim By jeśli uważasz, że może być więcej niż jeden, dodać dodatkową * na początku tak.:

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

Ale tutaj jest również naprawdę potężny sposób, w jaki możesz użyć preg_match do zrobienia tego, co prawdopodobnie próbujesz zrobić:

$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
}

Wyrażenia regularne mogą początkowo wydawać się zagmatwane, ale mogą być naprawdę potężne i być najlepszym przyjacielem, gdy je opanujesz! Powodzenia!

azoundria
źródło
1

Czemu...

Jest to prawdopodobnie przesada dla większości ludzi, ale dotyczy wielu rzeczy, których nie dotyczy każda z powyższych odpowiedzi. Z pozycji, których dotyczy, trzy były potrzebne do moich potrzeb. Przy ścisłym nawiasach klamrowych i porzucaniu komentarzy może to być nadal czytelne przy zaledwie 13 liniach kodu.

Dotyczy to następujących kwestii:

  • Wpływ na wydajność korzystania z REGEX vs strrpos / strstr / strripos / stristr.
  • Używanie strripos / strrpos, gdy znak / ciąg nie został znaleziony w ciągu.
  • Usuwanie z lewej lub prawej strony łańcucha (pierwsze lub ostatnie wystąpienie).
  • Rozróżnianie wielkości liter.
  • Chcąc mieć możliwość zwrócenia oryginalnego ciągu niezmienionego, jeśli nie znaleziono znaku / ciągu wyszukiwania.

Stosowanie:

Wyślij oryginalny ciąg, wyszukaj znak / ciąg, „R” / „L”, aby rozpocząć po prawej lub lewej stronie, prawda / fałsz, aby uwzględnić wielkość liter. Na przykład wyszukaj „tutaj” bez rozróżniania wielkości liter, w ciągu znaków zacznij od prawej strony.

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

Rezultatem byłoby „Teraz oto kilka słów”. Zmiana „R” na „L” spowoduje wyświetlenie: „Teraz”.

Oto funkcja:

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
    }           

}
Robert Mauro
źródło
Jeśli zignorujesz moją roboczą odpowiedź, byłbym wdzięczny, gdybyś powiedział dlaczego.
Robert Mauro
0

Użyj funkcji strstr .

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

echo $result ;

Trzeci parametr truemówi funkcji, aby zwróciła wszystko przed pierwszym wystąpieniem drugiego parametru.

Faisal
źródło
1
strtok($str, 'By')wygląda prościej
mu3
-2
$variable = substr($initial, 0, strpos($initial, "By"));

if (!empty($variable)) { echo $variable; } else { echo $initial; }
Valente
źródło