quitar - PHP explota la cadena, pero trata palabras entre comillas como una sola palabra
poner comillas en un string php (5)
En algunas situaciones, el poco conocido token_get_all()
podría ser ú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
)
¿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")
Para que el texto entre comillas se trate 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 para que las palabras entre comillas sean tratadas como una sola palabra?
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"
}
Puede usar un preg_match_all(...)
:
$text = ''Lorem ipsum "dolor sit amet" consectetur "adipiscing //"elit" dolor'';
preg_match_all(''/"(?:////.|[^////"])*"|/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 representa las comillas escapadas dentro de las cadenas entre comillas.
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 que coincida con %22
lugar de comillas dobles, harías:
preg_match_all(''/%22(?:////.|(?!%22).)*%22|/S+/'', $text, $matches);
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);
Vine aquí con un complejo problema de división de cuerdas similar a este, pero ninguna de las respuestas aquí hizo exactamente lo que yo quería, así que escribí el mío.
Lo estoy publicando aquí en caso de que sea útil para otra persona.
Esta es probablemente una forma muy lenta e ineficiente de hacerlo, pero funciona para mí.
function explode_adv($openers, $closers, $togglers, $delimiters, $str)
{
$chars = str_split($str);
$parts = [];
$nextpart = "";
$toggle_states = array_fill_keys($togglers, false); // true = now inside, false = now outside
$depth = 0;
foreach($chars as $char)
{
if(in_array($char, $openers))
$depth++;
elseif(in_array($char, $closers))
$depth--;
elseif(in_array($char, $togglers))
{
if($toggle_states[$char])
$depth--; // we are inside a toggle block, leave it and decrease the depth
else
// we are outside a toggle block, enter it and increase the depth
$depth++;
// invert the toggle block state
$toggle_states[$char] = !$toggle_states[$char];
}
else
$nextpart .= $char;
if($depth < 0) $depth = 0;
if(in_array($char, $delimiters) &&
$depth == 0 &&
!in_array($char, $closers))
{
$parts[] = substr($nextpart, 0, -1);
$nextpart = "";
}
}
if(strlen($nextpart) > 0)
$parts[] = $nextpart;
return $parts;
}
El uso es el siguiente. explode_adv
toma 5 argumentos:
- Una serie de caracteres que abren un bloque, por ejemplo
[
,(
, etc. - Una matriz de caracteres que cierra un bloque, por ejemplo
]
,)
, etc. - Una matriz de caracteres que alternan un bloque, por ejemplo,
"
,''
, etc. - Una matriz de caracteres que debería provocar una división en la siguiente parte.
- La cuerda para trabajar.
Este método probablemente tenga defectos: las ediciones son bienvenidas.