我试图在不使用解析器的情况下从CSV文件中分离出一行,我需要做的就是使用php根据逗号分割字符串。如果您在输入中没有逗号,则这本身就相当容易,事实并非如此。我想忽略用双引号封装的逗号。
完全无视最后一句,我决定将问题本身改为:
我想基于逗号分隔字符串,前面没有双引号或分散的双引号对。
示例:
text,"some,"chars,chars"more,""text",
* x * x *
其中*是匹配而x不是。
这是否超出了正则表达式的能力,如果没有,是否有正则表达式可以处理这种输入?
答案 0 :(得分:1)
我确信这可以写得更好,但这里有一个适合您案例的变体:
preg_match_all('/
\s* ((?: (?=.|(?<=,)$) [^",]* | "(?: ""|[^"]* )+" )+) \s* (?:,|$) /xms',
$line, $matches
)
and print_r($matches[1]);
但它不尊重其他典型的CSV规则。我通常希望\"
成为转义中的双引号。混合引用和未引用的子串也非常不标准。它缺乏任何形式的验证,因此只会忽略任何最后的引用 - 无论是否配对都是正确的。
对于您的测试字符串:
[0] => text
[1] => "some,"chars
[2] => chars"more,""text"
[3] =>
答案 1 :(得分:1)
如果您的CSV文件正确(每个字段以“或不包含”开头和结尾),那么您可以使用递归函数解析字符串,如下所示:
$csvString = 'zero,"o,ne",two,"thr,ee"';
function parseCsv($string, &$result)
{
$regex = '/^((".*")|([^"].*))(,(.*))?$/U';
$matches = array();
preg_match($regex, $string, $matches);
$result[] = $matches[1];
if(isset($matches[5]))
{
parseCsv($matches[5], $result);
}
}
$result = array();
parseCsv($csvString, $result);
var_dump($result);
请注意,尚未使用包含(转义)引号的带引号的字符串对此进行测试。它还将引号保留在引用的字符串周围。
上述功能的结果是
array
0 => string 'zero' (length=4)
1 => string '"o,ne"' (length=6)
2 => string 'two' (length=3)
3 => string '"thr,ee"' (length=8)