$escape
参数完全不直观,但它没有损坏。以下是 `fgetcsv()` 的行为细分。在我的示例中,我使用了下划线 (_) 来表示空格,并使用了方括号 ([]) 来表示各个字段
- 如果每个字段中的前导空格紧接在引号之前,则将被去除:___"foo" -> [foo]
- 每个字段只能有一个引号,尽管它将与出现在结束引号和下一个分隔符/换行符之间的任何数据连接起来,包括任何尾随空格:___"foo"_"bar"__ -> [foo_"bar"__]
如果字段不是以(开头空格 +)分隔符开头,则整个字段将被解释为原始数据,即使字段中其他位置出现分隔符字符:_foo"bar"_ -> [_foo"bar"_ ]
分隔符不能在分隔符外部转义,而必须将其包含在内。分隔符不需要在分隔符内部转义:"foo,bar","baz,qux" -> [foo,bar][baz,qux];foo\,bar -> [foo\][bar];"foo\,bar" -> [foo\,bar]
单引号内的双引号将转换为单引号:"foobar" -> [foobar];"foo""bar" -> [foo"bar];"""foo""" -> ["foo"];""foo"" -> [foo""](空引号后跟原始数据)
$escape 参数按预期工作,但与分隔符不同的是,它不会被取消转义。需要在代码的其他地方取消转义数据:"\"foo\"" -> [\"foo\"];"foo\"bar" -> [foo\"bar]
注意:以下数据(这是一个非常常见的问题)是无效的:"\"。它的结构等同于 @,或者换句话说,是一个打开的分隔符、一些数据和没有关闭的分隔符。
可以使用以下函数获得预期的行为
<?php
function fgetcsv_unescape_enclosures_and_escapes($fh, $length = 0, $delimiter = ',', $enclosure = '"', $escape = '\\') {
$fields = fgetcsv($fh, $length, $delimiter, $enclosure, $escape);
if ($fields) {
$regex_enclosure = preg_quote($enclosure);
$regex_escape = preg_quote($escape);
$fields = preg_replace("/{$regex_escape}({$regex_enclosure}|{$regex_escape})/", '$1', $fields);
}
return $fields;
}
function fgetcsv_unescape_all($fh, $length = 0, $delimiter = ',', $enclosure = '"', $escape = '\\') {
$fields = fgetcsv($fh, $length, $delimiter, $enclosure, $escape);
if ($fields) {
$regex_escape = preg_quote($escape);
$fields = preg_replace("/{$regex_escape}(.)/s", '$1', $fields);
}
return $fields;
}
function fgetcsv_unescape_all_strip_last($fh, $length = 0, $delimiter = ',', $enclosure = '"', $escape = '\\') {
$fields = fgetcsv($fh, $length, $delimiter, $enclosure, $escape);
if ($fields) {
$regex_escape = preg_quote($escape);
$fields = preg_replace("/{$regex_escape}(.?)/s", '$1', $fields);
}
return $fields;
}
?>
注意:理想情况下,分隔符外部不应该有任何未转义的转义字符;字段应该被包含并转义。如果存在任何未转义的转义字符,则它们最终也可能被删除,具体取决于使用的函数。