两天前,我开始研究代码解析器而且卡住了。
如何用不在括号内的逗号分隔字符串,让我告诉你我的意思:
我要解析这个字符串:
one, two, three, (four, (five, six), (ten)), seven
我想得到这个结果:
array(
"one";
"two";
"three";
"(four, (five, six), (ten))";
"seven"
)
但我得到了:
array(
"one";
"two";
"three";
"(four";
"(five";
"six)";
"(ten))";
"seven"
)
我如何在PHP RegEx中执行此操作。
提前谢谢!
答案 0 :(得分:11)
您可以更轻松地做到这一点:
preg_match_all('/[^(,\s]+|\([^)]+\)/', $str, $matches)
但是如果使用真正的解析器会更好。也许是这样的:
$str = 'one, two, three, (four, (five, six), (ten)), seven';
$buffer = '';
$stack = array();
$depth = 0;
$len = strlen($str);
for ($i=0; $i<$len; $i++) {
$char = $str[$i];
switch ($char) {
case '(':
$depth++;
break;
case ',':
if (!$depth) {
if ($buffer !== '') {
$stack[] = $buffer;
$buffer = '';
}
continue 2;
}
break;
case ' ':
if (!$depth) {
continue 2;
}
break;
case ')':
if ($depth) {
$depth--;
} else {
$stack[] = $buffer.$char;
$buffer = '';
continue 2;
}
break;
}
$buffer .= $char;
}
if ($buffer !== '') {
$stack[] = $buffer;
}
var_dump($stack);
答案 1 :(得分:7)
嗯...确定已标记为已回答,但由于您要求一个简单的解决方案,我会尽力尝试:
<?php
$test = "one, two, three, , , ,(four, five, six), seven, (eight, nine)";
$split = "/([(].*?[)])|(\w)+/";
preg_match_all($split, $test, $out);
print_r($out[0]);
die();
?>
输出
Array
(
[0] => one
[1] => two
[2] => three
[3] => (four, five, six)
[4] => seven
[5] => (eight, nine)
)
答案 2 :(得分:5)
你不能,直接。你至少需要可变宽度的lookbehind,最后我知道PHP的PCRE只有固定宽度的lookbehind。
我的第一个建议是首先从字符串中提取带括号的表达式。但是,我对你的实际问题一无所知,所以我不知道这是否可行。
答案 3 :(得分:2)
我想不出使用单个正则表达式来做到这一点的方法,但是很容易将一些有效的东西混在一起:
function process($data)
{
$entries = array();
$filteredData = $data;
if (preg_match_all("/\(([^)]*)\)/", $data, $matches)) {
$entries = $matches[0];
$filteredData = preg_replace("/\(([^)]*)\)/", "-placeholder-", $data);
}
$arr = array_map("trim", explode(",", $filteredData));
if (!$entries) {
return $arr;
}
$j = 0;
foreach ($arr as $i => $entry) {
if ($entry != "-placeholder-") {
continue;
}
$arr[$i] = $entries[$j];
$j++;
}
return $arr;
}
如果你这样调用它:
$data = "one, two, three, (four, five, six), seven, (eight, nine)";
print_r(process($data));
输出:
Array
(
[0] => one
[1] => two
[2] => three
[3] => (four, five, six)
[4] => seven
[5] => (eight, nine)
)
答案 4 :(得分:2)
笨拙,但它确实起作用......
<?php
function split_by_commas($string) {
preg_match_all("/\(.+?\)/", $string, $result);
$problem_children = $result[0];
$i = 0;
$temp = array();
foreach ($problem_children as $submatch) {
$marker = '__'.$i++.'__';
$temp[$marker] = $submatch;
$string = str_replace($submatch, $marker, $string);
}
$result = explode(",", $string);
foreach ($result as $key => $item) {
$item = trim($item);
$result[$key] = isset($temp[$item])?$temp[$item]:$item;
}
return $result;
}
$test = "one, two, three, (four, five, six), seven, (eight, nine), ten";
print_r(split_by_commas($test));
?>
答案 5 :(得分:1)
我担心解析嵌套括号可能非常困难
one, two, (three, (four, five))
只有RegExp。
答案 6 :(得分:1)
我觉得值得注意的是,你应该总是避免使用正则表达式。为此,您应该知道对于PHP 5.3+,您可以使用str_getcsv()。但是,如果您正在处理文件(或文件流),例如CSV文件,那么函数fgetcsv()可能就是您所需要的,并且自PHP4起就可以使用。
最后,我很惊讶没有人使用preg_split(),或者根据需要不能使用它?