Мне нужно разделить строку пробелами, но фраза в кавычках должна быть сохранена нераскрытой. Пример:
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);