Как я могу найти все пробелы, кроме тех, которые заключены в кавычки? - PullRequest
7 голосов
/ 12 ноября 2009

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

  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. Есть связанный вопрос , но я не думаю, что он работает в моем случае. Принятый ответ обеспечивает регулярное выражение для поиска слов вместо пробелов.

Ответы [ 5 ]

9 голосов
/ 12 ноября 2009

С помощью пользователя 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, регулярное выражение, которое будет работать (избавлено от \ G и \ K):

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

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

0 голосов
/ 12 ноября 2009
$test = 'word1 word2 "this is a phrase" word3 word4 "this is a second phrase" word5';
preg_match_all( '/([^"\s]+)|("([^"]+)")/', $test, $matches);
0 голосов
/ 12 ноября 2009

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

<?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
)
0 голосов
/ 12 ноября 2009

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

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

$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);
0 голосов
/ 12 ноября 2009

при условии, что ваши кавычки четко определены, т. Е. Попарно, вы можете взорваться и пройти цикл за каждые 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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...