Remover parte de uma sequência após um determinado caractere

144

Eu só estou querendo saber como eu poderia remover tudo depois de uma certa substring em PHP

ex:

Posted On April 6th By Some Dude

Gostaria de tê-lo para que ele remova todo o texto, incluindo e depois a sub string "By"

obrigado

Belgin Fish
fonte
1
E se a sub-string ocorrer duas vezes (ou mais)?
Bart Kiers
18
Apenas como nota, se você estiver fazendo isso para poder pegar o conteúdo de outra pessoa e apresentá-lo em seu próprio site, não .
ceejayoz
Eu concordo com ceejayoz. Parece que você está tentando usar conteúdo ao qual realmente não tem acesso e está tentando remover qualquer referência ao autor original. Isso não seria muito bom ...
selfawaresoup
2
Alternativa grande solução stackoverflow.com/a/9315908/1518921 :)
Guilherme Nascimento
1
Na verdade, é comum precisar fazer esse tipo de coisa por motivos legítimos ao trabalhar com conteúdo gerado por um CMS. O motivo é que você nunca deseja mexer com o código real que cria um trecho como esse, porque você estará quebrando suas atualizações; então, você deixa fazer o que faz, e faz o que faz.
Nosajimiki 15/06

Respostas:

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

Em inglês simples: dê-me a parte da sequência começando no início e terminando na posição em que você encontrou o deliminador pela primeira vez.

Austin Fitzpatrick
fonte
11
Que tal "só fazer isso se" por "existir"?
Alisso
3
Você está certo. strpos retornará FALSE se "By" não for encontrado. substr retornará uma string vazia se o comprimento fornecido for falso. Na prática, provavelmente seria útil verificar se "By" existe e somente fazer isso se existir (caso contrário, apenas deixar a string em paz).
Austin Fitzpatrick
13
Isso funciona: strpos ($ variable, "By")? substr ($ variável, 0, strpos ($ variável, "Por")): $ variável;
Noah Gary
Eu coloquei uma resposta que acho que aborda tudo abaixo e também explica maneiras de lidar com todos os tipos de coisas, como não diferencia maiúsculas de minúsculas, várias ocorrências e expressões regulares. Se alguém quiser fazer algo mais flexível ou não tiver controle sobre a entrada, provavelmente vale a pena conferir.
Azoundria
1
Funciona perfeito para mim @Goahnary!
Denis 25/05
106

Se você estiver usando o PHP 5.3 ou superior, dê uma olhada no sinalizador $ before_needle de strstr ()

$s = 'Posted On April 6th By Some Dude';
echo strstr($s, 'By', true);
VolkerK
fonte
4
Obrigado, esta é a resposta correta atualmente !
Matmarbon
59
Observe que ele retornará FALSEse parte da string não for encontrada. Portanto, a solução poderia ser:echo strstr($s, 'By', true) ?: $s;
kenorb
6
^^^ A resposta de kenorb deve ser a resposta aceita hoje. Outra alternativa seria de squarecandy explode(' By', $s)[0]IMHO
Zack Morris
De fato, a verificação da existência do kenorb é a maneira de fazê-lo, mesmo que não seja necessário testar a string.
BarryMode
Só aqui para dizer que o método de @ kenorb são os peitos.
Comendador Quinn
32

Que tal usar explode:

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

Vantagens:

squarecandy
fonte
@bkac - O que há de errado com o antiquado, desde que funcione e não seja depreciado?
Squarecandy
3
Isso elimina a verificação extra da existência da cadeia de caracteres delimitadora exigida pela resposta aceita.
David Cullen
17

Você poderia fazer:

$posted = preg_replace('/ By.*/', '', $posted);
echo $posted;
JYelton
fonte
4
+1 É o único que funciona se os caracteres de controle não estão presentes (ao contrário dos outros que retornam uma string vazia se os caracteres de controle não estão presentes na cadeia de origem)
Tom Auger
9

Um método seria:

$str = 'Posted On April 6th By Some Dude';
echo strtok($str, 'By'); // Posted On April 6th
HADI
fonte
Essa é a melhor resposta que funciona, mesmo que By não esteja na string, a resposta substr está errada porque, por não existir, ela falha.
neoteknic
Isso está incorreto: a função não será dividida por By, mas por qualquer caractere no segundo parâmetro. Ou seja, ele será dividido por um Bou por um y. Tecnicamente, não está recebendo tudo antes de um By.
MSB
Cuidado: strtok retornará a parte da sequência após o caractere, se for o primeiro caractere da sequência, por exemplo, strtok('a:b', ':')retornará, amas strtok(':b', ':')retornará b, não uma sequência vazia, como seria de esperar.
Comendador Quinn
6

Tente isso.

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

Uso:

<?php
    //returns Apples
    $clean_string= strip_after_string ("Apples, Oranges, Banannas",",");
?>
Tim Yobson
fonte
Seria muito melhor nomear a função strip_after_string em vez de sas e ter uma base de código cheia de inicialismos enigmáticos. Esta é a minha resposta mais legível favorita para esta pergunta.
Anther
5

A resposta de Austin funciona no seu caso de exemplo.

De uma maneira mais geral, seria bom examinar as funções de expressão regular quando a substring na qual você está dividindo pode diferir entre as strings:

$ variável = preg_replace ('/ Por. * /', '', $ variável);
jemfinch
fonte
+1, está certo. Se você também deseja dividir em "Autor:" ou "Escrito por:" Ou "Usado com o consentimento de:", provavelmente seria mais fácil fazer uma expressão regular. Quando eu não faço qualquer lógica regex, porém, eu tendem a evitá-los como eles parecem imediatamente adicionar um nível de complexidade ao código (pelo menos para mim)
Austin Fitzpatrick
4

Você pode usar liste explodefunções:

list($result) = explode("By", "Posted On April 6th By Some Dude", 2);
// $result is "Posted On April 6th "
Salman A
fonte
Este é o mais preciso. Como eu gostaria de poder votar para este duas vezes
John Max
4
$var = "Posted On April 6th By Some Dude";
$new_var = substr($var, 0, strpos($var, " By"));
Tim Cooper
fonte
2

preg_replace oferece uma maneira:

$newText = preg_replace('/\bBy.*$/', '', $text);
fora
fonte
2

Usando expressão regular: $string = preg_replace('/\s+By.*$/', '', $string)

Ming-Tang
fonte
Inclua algumas explicações nesta resposta somente de código.
Mckmackusa 17/07/2018
2

Abaixo está o método mais eficiente (em tempo de execução) para cortar tudo após o primeiro By em uma string. Se By não existir, a cadeia completa será retornada. O resultado está em $ 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"

Se você não quer fazer distinção entre maiúsculas e minúsculas, use stripos em vez de strpos. Se você acha que By pode existir mais de uma vez e deseja cortar tudo após a última ocorrência, use strrpos .

Abaixo está um método menos eficiente, mas ocupa menos espaço de código. Esse método também é mais flexível e permite fazer qualquer expressão regular.

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

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

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

Por exemplo, se você deseja remover tudo após o dia:

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

Para não diferenciar maiúsculas de minúsculas, adicione o modificador i como este:

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

Para obter tudo após o último por se você acha que pode haver mais de um, adicionar um extra * no início como este.:

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

Mas aqui também é uma maneira realmente poderosa de usar preg_match para fazer o que você está tentando fazer:

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

Expressões regulares podem parecer confusas no início, mas podem ser realmente poderosas e seu melhor amigo depois que você as dominar! Boa sorte!

azoundria
fonte
1

Por quê...

Isso provavelmente é um exagero para as necessidades da maioria das pessoas, mas aborda várias coisas que cada resposta individual acima não aborda. Dos itens abordados, três deles foram necessários para minhas necessidades. Com bracketing apertado e eliminação dos comentários, isso ainda pode permanecer legível em apenas 13 linhas de código.

Isso aborda o seguinte:

  • Impacto no desempenho do uso do REGEX vs strrpos / strstr / strripos / stristr.
  • Usando strripos / strrpos quando o caractere / string não for encontrado na string.
  • Removendo do lado esquerdo ou direito da string (primeira ou última ocorrência).
  • Sensibilidade de CaSe.
  • Desejando a capacidade de retornar a string original inalterada se a pesquisa char / string não for encontrada.

Uso:

Envie a string original, pesquise char / string, "R" / "L" para iniciar no lado direito ou esquerdo, verdadeiro / falso para diferenciar maiúsculas e minúsculas. Por exemplo, procure por "aqui" sem distinção entre maiúsculas e minúsculas, na sequência, inicie o lado direito.

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

A saída seria "Agora, aqui estão algumas palavras". Alterar o "R" para um "L" produziria: "Agora".

Aqui está a função:

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
fonte
Se você recusar minha resposta de trabalho, seria apreciado se você declarasse o porquê.
Robert Mauro
0

Use a função strstr .

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

echo $result ;

O terceiro parâmetro truediz à função para retornar tudo antes da primeira ocorrência do segundo parâmetro.

Faisal
fonte
1
strtok($str, 'By')parece mais simples
mu3 19/10/19
-2
$variable = substr($initial, 0, strpos($initial, "By"));

if (!empty($variable)) { echo $variable; } else { echo $initial; }
valente
fonte