Eliminar parte de una cadena después de cierto carácter

144

Me pregunto cómo podría eliminar todo después de cierta subcadena en PHP

ex:

Posted On April 6th By Some Dude

Me gustaría tenerlo para que elimine todo el texto, incluida, y después, la subcadena "Por"

Gracias

Pez Belgin
fuente
1
¿Qué pasa si la subcadena aparece dos veces (o más)?
Bart Kiers el
18
Solo como una nota, si está haciendo esto para poder tomar el contenido de otra persona y presentarlo en su propio sitio, no lo haga .
ceejayoz
Estoy de acuerdo con ceejayoz. Esto suena muy parecido a que estás tratando de usar contenido al que realmente no tienes acceso y estás tratando de eliminar cualquier referencia al autor original. Eso no sería muy agradable ...
selfawaresoup
2
Gran solución alternativa stackoverflow.com/a/9315908/1518921 :)
Guilherme Nascimento
1
En realidad, es común tener que hacer este tipo de cosas por razones legítimas cuando se trabaja con contenido generado por un CMS. La razón es que nunca querrás meterte con el código real que crea un fragmento como este porque estarás rompiendo tus actualizaciones; entonces, dejas que haga lo suyo, luego haces lo tuyo.
Nosajimiki

Respuestas:

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

En inglés simple: dame la parte de la cadena que comienza en el principio y termina en la posición donde te encuentras con el deliminador.

Austin Fitzpatrick
fuente
11
¿Qué pasa con "solo hacer esto si" por "existe?
Alisso
3
Tienes razón. strpos devolverá FALSE si no se encuentra "By". substr devolverá una cadena vacía si la longitud dada es falsa. En la práctica, probablemente sería útil verificar si "By" existe y luego solo hacer esto si es así (de lo contrario, dejar la cadena sola).
Austin Fitzpatrick
13
Esto funciona: strpos ($ variable, "By")? substr ($ variable, 0, strpos ($ variable, "Por")): $ variable;
Noah Gary
Pongo una respuesta que creo que aborda todo a continuación y también explica formas de lidiar con todo tipo de cosas como mayúsculas y minúsculas, ocurrencias múltiples y expresiones regulares. Si alguien quiere hacer algo más flexible o no tiene control sobre la entrada, probablemente valga la pena echarle un vistazo.
azoundria
1
¡Funciona perfecto para mí @Goahnary!
denis
106

Si está utilizando PHP 5.3+, eche un vistazo a la bandera $ before_needle de strstr ()

$s = 'Posted On April 6th By Some Dude';
echo strstr($s, 'By', true);
VolkerK
fuente
44
¡Gracias, esta es la respuesta correcta real hoy en día !
Matmarbon
59
Tenga en cuenta que volverá FALSEsi no se encuentra una parte de la cadena. Entonces la solución podría ser:echo strstr($s, 'By', true) ?: $s;
kenorb
66
^^^ La respuesta de Kenorb debería ser la respuesta aceptada hoy. otra alternativa sería el explode(' By', $s)[0]IMHO de squarecandy
Zack Morris
De hecho, la verificación de existencia de kenorb es la forma de hacerlo, aunque no es necesario probar la cadena.
BarryMode
Solo para decir que el método de @ kenorb son las tetas.
Quinn Comendant
32

¿Qué tal usar explode:

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

Ventajas:

Squarecandy
fuente
@bkac: ¿Qué hay de malo en el estilo antiguo siempre que funcione y no se deprecia?
squarecandy
3
Esto elimina la comprobación adicional de la existencia de la cadena delimitador requerida por la respuesta aceptada.
David Cullen
17

Podrías hacerlo:

$posted = preg_replace('/ By.*/', '', $posted);
echo $posted;
JYelton
fuente
44
+1 Es el único que funciona si los caracteres de control NO están presentes (a diferencia de los otros que devuelven una cadena vacía si los caracteres de control no están presentes en la cadena de origen)
Tom Auger
9

Un método sería:

$str = 'Posted On April 6th By Some Dude';
echo strtok($str, 'By'); // Posted On April 6th
Hadi
fuente
Esta es la mejor respuesta, incluso si By no está en la cadena, la respuesta substr es incorrecta porque, por no existir, falla.
neoteknic
Esto es incorrecto: la función no se dividirá por By, sino por cualquier carácter en el segundo parámetro. Es decir, se dividirá por cualquiera Bo y. Técnicamente, no está obteniendo todo antes de a By.
msb
Tenga cuidado: strtok devolverá la parte de la cadena después del carácter si es el primer carácter de la cadena, por ejemplo, strtok('a:b', ':')volverá apero strtok(':b', ':')volverá b, no una cadena vacía como cabría esperar.
Quinn Comandante
6

Prueba esto.

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
fuente
Sería mucho mejor nombrar la función strip_after_string en lugar de sas y tener una base de código llena de initialisms crípticos. Sin embargo, esta es mi respuesta favorita más legible a esta pregunta.
Antera
5

La respuesta de Austin funciona para su caso de ejemplo.

En términos más generales, haría bien en examinar las funciones de expresión regular cuando la subcadena en la que se está dividiendo puede diferir entre cadenas:

$ variable = preg_replace ('/ By. * /', '', $ variable);
jemfinch
fuente
+1, esto es correcto. Si también quisiera dividirse en "Autor:" o "Escrito por:" O "Utilizado con el consentimiento de:" probablemente sería más fácil hacer una expresión regular. Sin embargo, cuando no hago ninguna lógica regex, tiendo a evitarlos, ya que parecen agregar de inmediato un nivel de complejidad al código (al menos para mí)
Austin Fitzpatrick
4

Puedes usar listy explodefunciones:

list($result) = explode("By", "Posted On April 6th By Some Dude", 2);
// $result is "Posted On April 6th "
Salman A
fuente
Este es el más preciso. Cómo me gustaría poder votar por esto dos veces
John Max
4
$var = "Posted On April 6th By Some Dude";
$new_var = substr($var, 0, strpos($var, " By"));
Tim Cooper
fuente
2

preg_replace ofrece una forma:

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

Mediante el uso de expresiones regulares: $string = preg_replace('/\s+By.*$/', '', $string)

Ming-Tang
fuente
Incluya alguna explicación con esta respuesta de solo código.
mickmackusa
2

A continuación se muestra el método más eficiente (por tiempo de ejecución) para cortar todo después del primer By en una cadena. Si By no existe, se devuelve la cadena completa. El resultado está en $ 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"

Si no quiere ser sensible a mayúsculas y minúsculas, use stripos en lugar de strpos. Si cree que By podría existir más de una vez y desea cortar todo después de la última aparición, use strrpos .

A continuación se muestra un método menos eficiente, pero ocupa menos espacio en el código. Este método también es más flexible y le permite hacer cualquier expresión regular.

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

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

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

Por ejemplo, si desea eliminar todo después del día:

$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 mayúsculas y minúsculas, agregue el modificador i de esta manera:

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

Para que todo pase más allá del último Por si cree que puede haber más de uno, agregue un extra. * Al principio como este:

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

Pero aquí también hay una forma realmente poderosa de usar preg_match para hacer lo que intenta hacer:

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

Las expresiones regulares pueden parecer confusas al principio, ¡pero pueden ser realmente poderosas y tu mejor amigo una vez que las domines! ¡Buena suerte!

azoundria
fuente
1

Por qué...

Es probable que esto sea excesivo para las necesidades de la mayoría de las personas, pero aborda una serie de cosas que cada respuesta individual anterior no aborda. De los artículos que aborda, tres de ellos fueron necesarios para mis necesidades. Con un paréntesis apretado y dejando caer los comentarios, esto podría seguir siendo legible con solo 13 líneas de código.

Esto aborda lo siguiente:

  • Impacto en el rendimiento del uso de REGEX vs strrpos / strstr / strripos / stristr.
  • Usar strripos / strrpos cuando el carácter / cadena no se encuentra en la cadena.
  • Eliminación del lado izquierdo o derecho de la cadena (primera o última aparición).
  • CaSe Sensibilidad.
  • Deseando la capacidad de devolver la cadena original sin alterar si no se encuentra char / string.

Uso:

Envíe la cadena original, busque char / string, "R" / "L" para comenzar en el lado derecho o izquierdo, verdadero / falso para mayúsculas y minúsculas. Por ejemplo, busque "aquí" sin distinción entre mayúsculas y minúsculas, en cadena, comience por el lado derecho.

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

La salida sería "Ahora, aquí hay algunas palabras". Cambiar la "R" a una "L" generaría: "Ahora".

Aquí está la función:

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
fuente
Si rechaza mi respuesta de trabajo, le agradecería que dijera por qué.
Robert Mauro
0

Usa la función strstr .

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

echo $result ;

El tercer parámetro truele dice a la función que devuelva todo antes de la primera aparición del segundo parámetro.

Faisal
fuente
1
strtok($str, 'By')parece más simple
mu3
-2
$variable = substr($initial, 0, strpos($initial, "By"));

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