Регулярное выражение (предварительное разделение): как разделить на основе разделителя, исключая разделители, включенные в пару кавычек?
Я разделил это:
1 2 3 4/5/6 "7/8 9" 10
В это:
1
2
3
4
5
6
"7/8 9"
10
С помощью функции preg_split()
Итак, мой вопрос в том, как мне разделить на основе разделителя, исключая разделители внутри пары кавычек?
Я вроде как хочу сначала не заключать вещи в кавычки и в идеале хотел бы, чтобы это был один лайнер.
3 answers
Вы можете использовать следующее.
$text = '1 2 3 4/5/6 "7/8 9" 10';
$results = preg_split('~"[^"]*"(*SKIP)(*F)|[ /]+~', $text);
print_r($results);
Объяснение:
В левой части оператора чередования мы сопоставляем что-либо в кавычках, что приводит к сбою подшаблона , заставляя механизм регулярных выражений не повторять попытку подстроки с помощью управления обратным отслеживанием с помощью (*SKIP)
и (*F)
. Правая сторона оператора чередования соответствует либо символу пробела, либо косой черте, не заключенной в кавычки.
Выход
Array
(
[0] => 1
[1] => 2
[2] => 3
[3] => 4
[4] => 5
[5] => 6
[6] => "7/8 9"
[7] => 10
)
Вы можете использовать:
$s = '1 2 3 4/5/6 "7/8 9" 10';
$arr = preg_split('~("[^"]*")|[ /]+~', $s, -1, PREG_SPLIT_DELIM_CAPTURE|PREG_SPLIT_NO_EMPTY);
print_r( $arr );
ВЫХОД:
Array
(
[0] => 1
[1] => 2
[2] => 3
[3] => 4
[4] => 5
[5] => 6
[6] => "7/8 9"
[7] => 10
)
Другой способ с дополнительной группой:
$arr = preg_split('~(?:"[^"]*")?\K[/\s]+~', $s);
Шаблон "[^"]*"[/\s]+
соответствует части в кавычках, за которой следует один или несколько пробелов и косых черт. Но так как вы не хотите удалять части в кавычках, вы ставите \K
после этого. \K
удаляет все, что было сопоставлено слева, из результата сопоставления. С помощью этого трюка, когда часть в кавычках найдена, механизм регулярных выражений возвращает только пробелы или косые черты после и разделяет их.
Так как не всегда есть часть в кавычках перед пробелом или косая черта, вам нужно только сделать ее необязательной с группой без захвата (?:...)
и знаком вопроса ?