Как я могу взорвать следующую строку:
Lorem ipsum "dolor sit amet" consectetur "adipiscing elit" dolor
в
array("Lorem", "ipsum", "dolor sit amet", "consectetur", "adipiscing elit", "dolor")
Так что текст в цитате рассматривается как одно слово.
Вот что у меня есть сейчас:
$mytext = "Lorem ipsum %22dolor sit amet%22 consectetur %22adipiscing elit%22 dolor" $noquotes = str_replace("%22", "", $mytext"); $newarray = explode(" ", $noquotes);
но мой код делит каждое слово на массив. Как сделать слова внутри кавычек, которые рассматриваются как одно слово?
Вы можете использовать preg_match_all(...)
:
$text = 'Lorem ipsum "dolor sit amet" consectetur "adipiscing \\"elit" dolor'; preg_match_all('/"(?:\\\\.|[^\\\\"])*"|\S+/', $text, $matches); print_r($matches);
который будет производить:
Array ( [0] => Array ( [0] => Lorem [1] => ipsum [2] => "dolor sit amet" [3] => consectetur [4] => "adipiscing \"elit" [5] => dolor ) )
И, как вы можете видеть, он также учитывает скрытые кавычки внутри цитируемых строк.
РЕДАКТИРОВАТЬ
Краткое объяснение:
" # 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
И в случае сопоставления %22
вместо двойных кавычек вы бы сделали:
preg_match_all('/%22(?:\\\\.|(?!%22).)*%22|\S+/', $text, $matches);
Это было бы намного проще с str_getcsv()
.
$test = 'Lorem ipsum "dolor sit amet" consectetur "adipiscing elit" dolor'; var_dump(str_getcsv($test, ' '));
Дает тебе
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" }
Вы также можете попробовать эту функцию множественного разрыва
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);
В некоторых ситуациях малоизвестный token_get_all()
может оказаться полезным:
$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; } } }
Результаты:
Array ( [0] => Lorem [1] => ipsum [2] => dolor sit amet [3] => consectetur [4] => adipiscing elit [5] => dolor )
Я пришел сюда с сложной проблемой разделения строк, подобной этому, но ни один из ответов здесь не сделал именно то, что я хотел, поэтому я написал свой собственный.
Я размещаю его здесь, если это полезно кому-то другому.
Это, вероятно, очень медленный и неэффективный способ сделать это, но он работает для меня.
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; }
Использование выглядит следующим образом. explode_adv
принимает 5 аргументов:
[
, (
и т. Д.). ]
, )
и т. Д. "
, '
и т. Д. У этого метода, вероятно, есть недостатки – исправления приветствуются.