#php #regex #string #parsing #arguments
#php #регулярное выражение #строка #синтаксический анализ #аргументы
Вопрос:
Как я могу разбить строку на пробелы в PHP, соблюдая вложенные строки в кавычках? Я думаю, что должна быть какая-то команда для разбора этого типа строки как аргументов, но я не знаю, что это такое.
Пример строки:
$string = '12345 abcd "hello world" defgh "nice to meet you" 34554';
Обычно я использую одно из этих трех для разбиения строк. Но я не думаю, что у них есть возможность разбить строку, как я предлагаю.
$result = str_replace(' ',"n",$string);
$result = explode(' ',$string);
$result = preg_replace('#s#',"n",$string);
Результат:
12345
abcd
"hello
world"
defgh
"nice
to
meet
you"
34554
Желаемый результат:
12345
abcd
hello world
defgh
nice to meet you
34554
Обновить
Думаю, я был впечатлен parse_str
командой PHP для обработки переменных запроса URL и надеялся, что в PHP есть что-то I, что могло бы сработать для этого примера, вроде того, что getopt
делает для аргументов командной строки.
Ответ №1:
Для этого вы можете использовать fgetcsv() / str_getcsv().
<?php
$string = '12345 abcd "hello world" defgh "nice to meet you" 34554';
$row = str_getcsv($string, ' ');
var_dump($row);
С принтами
array(6) {
[0]=>
string(5) "12345"
[1]=>
string(4) "abcd"
[2]=>
string(11) "hello world"
[3]=>
string(5) "defgh"
[4]=>
string(16) "nice to meet you"
[5]=>
string(5) "34554"
}
Ответ №2:
Вы делаете что-то в неправильном порядке: сначала разбиваете кавычки (так вы легко выделите подстроки, заключенные в кавычки), затем разбиваете на основе пробелов.
Я предоставлю вам фактический код в качестве упражнения, но по сути:
12345 abcd "hello world" defgh "nice to meet you" 34554
становится
12345 abcd
hello world
defgh
nice to meet you
34554
Тогда вы бы разбили, используя пробелы, но только те строки, которые не были заключены в кавычки (это все строки с четными индексами, предполагая, что первая ячейка индексируется с 0, что является четным):
12345 abcd -> Split
hello world -> Don't split
defgh -> Split
nice to meet you -> Don't split
34554 -> Split
таким образом, это стало бы:
12345
abcd
hello world
defgh
nice to meet you
34554
Очевидно, что если у вас могут быть «экранированные кавычки», вам нужно будет как-то их учесть — также оставлено в качестве упражнения для читателя (на самом деле это просто).
Комментарии:
1. Спасибо. эти команды не должны были быть последовательными — просто показывали способы, которыми я обычно разбираю строки, просто чтобы немного уточнить вопрос.
2. @cwd Я знаю — просто даю вам некоторую логику, которая сработает (не эксперт по PHP, поэтому я не пытался вбросить туда какой-то код). Однако существует более одного способа сделать это, и некоторые из них могут работать лучше других (определенно не спорю, что мой лучший).
3. Спасибо. я сделал еще одно не в нижней части вопроса.
Ответ №3:
Вот так:
$s = '12345 abcd "hello world" defgh "nice to meet you" 34554';
$m = preg_split('/"([^"]*)"|([^s] )/', $s, -1, PREG_SPLIT_DELIM_CAPTURE);
$m = array_values(array_filter(array_map('trim', $m)));
var_export($m);
Вывод:
array (
0 => '12345',
1 => 'abcd',
2 => 'hello world',
3 => 'defgh',
4 => 'nice to meet you',
5 => '34554',
)
Ответ №4:
Это должно работать нормально:
function spaceExplode($var)
{
$chunks = explode('"', $var);
array_walk($chunks, function(amp;$text) {
$text = trim($text);
});
$subchunks = array();
foreach ($chunks as $key => $value) {
if ($key % 2 != 0) {
$subchunks[] = $value;
} else {
$subchunks = array_merge($subchunks, explode(' ', $value));
}
}
return $subchunks;
}
Другим способом было бы использовать strtok
(предложенный @Romain в его ответе, прежде чем он отредактировал его :)):
function tokenize($var, $char)
{
$tokens = array(strtok($var, $char));
do {
$tokens[] = strtok($char);
} while(end($tokens) !== false);
foreach ($tokens as $key => $token) {
$tokens[$key] = trim($token);
if (empty($tokens[$key])) {
unset($tokens[$key]);
}
}
return $tokens;
}
Комментарии:
1. По сути, это код, который реализует то, что я предложил в качестве способа работы (следовательно, я поддержал его: D).
2. Да, я только что прочитал ваш ответ. Не знал о
strtok
. Я думаю, что вместо этого следует использовать это решение.