PHP explota la cadena, pero trata las palabras entre comillas como una sola palabra

4 minutos de lectura

PHP explota la cadena pero trata las palabras entre comillas
timofey

¿Cómo puedo explotar la siguiente cadena:

Lorem ipsum "dolor sit amet" consectetur "adipiscing elit" dolor

dentro

array("Lorem", "ipsum", "dolor sit amet", "consectetur", "adipiscing elit", "dolor")

De modo que el texto entre comillas se trata como una sola palabra.

Esto es lo que tengo por ahora:

$mytext = "Lorem ipsum %22dolor sit amet%22 consectetur %22adipiscing elit%22 dolor"
$noquotes = str_replace("%22", "", $mytext");
$newarray = explode(" ", $noquotes);

pero mi código divide cada palabra en una matriz. ¿Cómo hago que las palabras entre comillas se traten como una sola palabra?

  • Esto suena como un trabajo para Regex

    – Condez

    4 de febrero de 2010 a las 19:10

  • Consulte también ¿Una función de explosión () que ignora los caracteres dentro de las comillas?

    – Bergi

    10/09/2013 a las 21:43

1646756946 684 PHP explota la cadena pero trata las palabras entre comillas
bart kiers

Podrías usar un preg_match_all(...):

$text="Lorem ipsum "dolor sit amet" consectetur "adipiscing \\"elit" dolor";
preg_match_all("https://stackoverflow.com/"(?:\\\\.|[^\\\\"])*"|\S+/', $text, $matches);
print_r($matches);

que producirá:

Array
(
    [0] => Array
        (
            [0] => Lorem
            [1] => ipsum
            [2] => "dolor sit amet"
            [3] => consectetur
            [4] => "adipiscing \"elit"
            [5] => dolor
        )

)

Y como puede ver, también tiene en cuenta las comillas escapadas dentro de las cadenas entrecomilladas.

EDITAR

Una breve explicación:

"           # match the character '"'
(?:         # start non-capture group 1 
  \\        #   match the character '\'
  .         #   match any character except line breaks
  |         #   OR
  [^\\"]    #   match any character except '\' and '"'
)*          # end non-capture group 1 and repeat it zero or more times
"           # match the character '"'
|           # OR
\S+         # match a non-whitespace character: [^\s] and repeat it one or more times

Y en caso de coincidencia %22 en lugar de comillas dobles, harías:

preg_match_all('/%22(?:\\\\.|(?!%22).)*%22|\S+/', $text, $matches);

  • ¿Hay alguna razón para no usar preg_split en lugar de preg_match_all? parece un ajuste más natural en mi opinión.

    – prodigitalson

    4 de febrero de 2010 a las 19:20

  • ¡Eso es genial! ¡Tendré que estudiar el código un poco para darme cuenta de lo que acaba de suceder! Gracias

    – timofey

    4 de febrero de 2010 a las 19:21

  • @prodigitalson: no, usando preg_split(...) no puede tener en cuenta los caracteres escapados. preg_match_all(...) “se comporta” más como un analizador, que es lo más natural que se puede hacer aquí. Además, usando un preg_split(...)deberá mirar hacia adelante en cada espacio para ver cuántas comillas hay delante de él, lo que lo convierte en un O(n^2) operación: no hay problema para cadenas pequeñas, pero puede disminuir el tiempo de ejecución cuando se trata de cadenas más grandes.

    – Bart Kier

    4 de febrero de 2010 a las 19:31

  • @timofey, mira mi edición. No dude en solicitar más aclaraciones si no le queda claro: usted es quien mantiene el código, por lo que debe comprenderlo (y estaré más que feliz de proporcionar información adicional si es necesario).

    – Bart Kier

    4 de febrero de 2010 a las 19:36


  • Gracias Bart K! Ya estaba buscando en Google respuestas sobre eso 🙂

    – timofey

    4 de febrero de 2010 a las 19:39

PHP explota la cadena pero trata las palabras entre comillas
petah

Esto hubiera sido mucho más fácil con str_getcsv().

$test="Lorem ipsum "dolor sit amet" consectetur "adipiscing elit" dolor";
var_dump(str_getcsv($test, ' '));

Te dio

array(6) {
  [0]=>
  string(5) "Lorem"
  [1]=>
  string(5) "ipsum"
  [2]=>
  string(14) "dolor sit amet"
  [3]=>
  string(11) "consectetur"
  [4]=>
  string(15) "adipiscing elit"
  [5]=>
  string(5) "dolor"
}

  • Esto funciona en mi máquina de desarrollo, pero no en mi servidor de producción. :-/

    – Martín Uding

    17 de marzo de 2012 a las 18:22

  • str_getcsv requiere PHP 5.3.

    – armakuni

    2 de agosto de 2013 a las 6:18

  • Tenga en cuenta que “ignora” las comillas. Si necesita que estén allí en la división también, esto no funcionará.

    – Gayan Dasanayake

    12 de abril de 2018 a las 14:38

  • Hice algunas pruebas de velocidad y preg_match_all es de 3 a 5 veces más rápido. Probablemente no sea un problema para la mayoría de las personas, especialmente si no necesitan las comillas (en este caso es mucho más fácil de usar), pero creo que vale la pena mencionarlo.

    – errar

    1 de enero de 2019 a las 13:51

  • @err ¿quieres compartir tus pruebas?

    – Petaj

    5 de enero de 2019 a las 9:12

PHP explota la cadena pero trata las palabras entre comillas
Nikz

También puedes probar esta función de explosión múltiple

function multiexplode ($delimiters,$string)
{

$ready = str_replace($delimiters, $delimiters[0], $string);
$launch = explode($delimiters[0], $ready);
return  $launch;
}

$text = "here is a sample: this text, and this will be exploded. this also | this one too :)";
$exploded = multiexplode(array(",",".","|",":"),$text);

print_r($exploded);

  • Esta respuesta es buena, pero si le pide que se divida en espacios y comillas, se dividirá en espacios dentro de las comillas.

    – starbeamrainbowlabs

    20 mayo 2015 a las 16:38

1646756947 408 PHP explota la cadena pero trata las palabras entre comillas
clong

En algunas situaciones lo poco conocido token_get_all() podría resultar útil:

$tokens = token_get_all("<?php $text ?>");
$separator=" ";
$items = array();
$item = "";
$last = count($tokens) - 1;
foreach($tokens as $index => $token) {
    if($index != 0 && $index != $last) {
        if(count($token) == 3) {
            if($token[0] == T_CONSTANT_ENCAPSED_STRING) {
                $token = substr($token[1], 1, -1);
            } else {
                $token = $token[1];
            }
        }
        if($token == $separator) {
            $items[] = $item;
            $item = "";
        } else {
            $item .= $token;
        }
    }
}

Resultados:

Array
(
    [0] => Lorem
    [1] => ipsum
    [2] => dolor sit amet
    [3] => consectetur
    [4] => adipiscing elit
    [5] => dolor
)

¿Ha sido útil esta solución?

Esta web utiliza cookies propias y de terceros para su correcto funcionamiento y para fines analíticos y para mostrarte publicidad relacionada con sus preferencias en base a un perfil elaborado a partir de tus hábitos de navegación. Al hacer clic en el botón Aceptar, acepta el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. Configurar y más información
Privacidad