PHP взорвать строку, но рассматривать слова в кавычках как одно слово

Как я могу взорвать следующую строку:

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 аргументов:

  1. Массив символов, которые открывают блок – например, [ , ( и т. Д.).
  2. Массив символов, которые закрывают блок – например ] , ) и т. Д.
  3. Массив символов, которые переключают блок – например, " , ' и т. Д.
  4. Массив символов, который должен вызвать разделение на следующую часть.
  5. Строка для работы.

У этого метода, вероятно, есть недостатки – исправления приветствуются.