Как я могу найти все пробелы, исключая те, которые заключены между кавычками?

Мне нужно разделить строку пробелами, но фраза в кавычках должна быть сохранена нераскрытой. Пример:

word1 word2 "this is a phrase" word3 word4 "this is a second phrase" word5 

это должно привести к массиву после preg_split:

 array( [0] => 'word1', [1] => 'word2', [2] => 'this is a phrase', [3] => 'word3', [4] => 'word4', [5] => 'this is a second phrase', [6] => 'word5' ) 

Как мне написать это регулярное выражение?

PS. Существует связанный с этим вопрос , но я не думаю, что это работает в моем случае. Принятый ответ предоставляет регулярное выражение для поиска слов вместо пробелов.

С помощью пользователя MizardX из #regex irc channel (irc.freenode.net) было найдено решение. Он поддерживает одиночные кавычки.

 $str= 'word1 word2 \'this is a phrase\' word3 word4 "this is a second phrase" word5 word1 word2 "this is a phrase" word3 word4 "this is a second phrase" word5'; $regexp = '/\G(?:"[^"]*"|\'[^\']*\'|[^"\'\s]+)*\K\s+/'; $arr = preg_split($regexp, $str); print_r($arr); 

Результат:

 Array ( [0] => word1 [1] => word2 [2] => 'this is a phrase' [3] => word3 [4] => word4 [5] => "this is a second phrase" [6] => word5 [7] => word1 [8] => word2 [9] => "this is a phrase" [10] => word3 [11] => word4 [12] => "this is a second phrase" [13] => word5 ) 

PS. Единственным недостатком является то, что это регулярное выражение работает только для PCRE 7.

Оказалось, что на рабочем сервере у меня нет поддержки PCRE 7, там установлен только PCRE 6. Несмотря на то, что он не такой гибкий, как предыдущий для PCRE 7, regexp, который будет работать (избавился от \ G и \ K):

 /(?:"[^"]*"|\'[^\']*\'|[^"\'\s]+)+/ 

Для данного входного результата такой же, как и выше.

предполагая, что ваши кавычки четко определены, т. е. попарно, вы можете взорваться и пройти через цикл каждые 2 поля. например

 $str = "word1 word2 \"this is a phrase\" word3 word4 \"this is a second phrase\" word5 word6 \"lastword\""; print $str ."\n"; $s = explode('"',$str); for($i=1;$i<count($s);$i+=2){ if ( strpos($s[$i] ," ")!==FALSE) { print "Spaces found: $s[$i]\n"; } } 

вывод

 $ php test.php Spaces found: this is a phrase Spaces found: this is a second phrase 

Не требуется сложное регулярное выражение.

использование регулярного выражения из другого вопроса, который вы связали, довольно легко?

 <?php $string = 'word1 word2 "this is a phrase" word3 word4 "this is a second phrase" word5'; preg_match_all( '/(\w+|"[\w\s]*")+/' , $string , $matches ); print_r( $matches[1] ); ?> 

вывод:

 Array ( [0] => word1 [1] => word2 [2] => "this is a phrase" [3] => word3 [4] => word4 [5] => "this is a second phrase" [6] => word5 ) 

Кто-нибудь хочет сравнить токенинг против регулярного выражения? Я предполагаю, что функция explode () немного слишком высока для любой скорости. Тем не менее, вот еще один метод:

(отредактирован, потому что я забыл случай else для хранения цитируемой строки)

 $str = 'word1 word2 "this is a phrase" word3 word4 "this is a second phrase" word5'; // initialize storage array $arr = array(); // initialize count $count = 0; // split on quote $tok = strtok($str, '"'); while ($tok !== false) { // even operations not in quotes $arr = ($count % 2 == 0) ? array_merge($arr, explode(' ', trim($tok))) : array_merge($arr, array(trim($tok))); $tok = strtok('"'); ++$count; } // output results var_dump($arr); 
 $test = 'word1 word2 "this is a phrase" word3 word4 "this is a second phrase" word5'; preg_match_all( '/([^"\s]+)|("([^"]+)")/', $test, $matches);