php str_getcsv()不忽略带引号的新行

2q5ifsrm  于 2022-12-10  发布在  PHP
关注(0)|答案(5)|浏览(133)

我需要解析一个CSV字符串,第一步,我想从中获取行。我使用str_getcsv函数来完成,但即使在最基本的情况下,它似乎也失败了-新行被引号包围。

$rows = '7;"Hi
";3';
$array = str_getcsv($rows,"\n",'"');
print_r($array);

结果应该是只有一个值的数组,但我得到了两个--令人惊讶的是,引用的新行是...

result:
Array
(
    [0] => 7;"Hi
    [1] => ;3
)

我做错了什么?
编辑:奇怪,但当我试着

$rows = '7;"Hi
";3
8;Hello;6';

结果是

Array
(
    [0] => 7;"Hi
    [1] => ;3
8;Hello;6
)
hm2xizp9

hm2xizp91#

看起来str_getcsv()不允许在字符串字段中有换行符,并且在不检查新行是否在字段中的情况下通过换行符解析行。有必要使用不同于此函数的东西,它只是工作得不那么好。
我找到了直接解析CSV的代码,而不需要将其解析为用户normadize -a- gmail -d- comstr_getcsv()函数的man page行。所缺少的是它不使用第一行的值作为其他行的键。

function parse_csv ($csv_string, $delimiter = ",", $skip_empty_lines = true, $trim_fields = true)
{
    $enc = preg_replace('/(?<!")""/', '!!Q!!', $csv_string);
    $enc = preg_replace_callback(
        '/"(.*?)"/s',
        function ($field) {
            return urlencode(utf8_encode($field[1]));
        },
        $enc
    );
    $lines = preg_split($skip_empty_lines ? ($trim_fields ? '/( *\R)+/s' : '/\R+/s') : '/\R/s', $enc);
    return array_map(
        function ($line) use ($delimiter, $trim_fields) {
            $fields = $trim_fields ? array_map('trim', explode($delimiter, $line)) : explode($delimiter, $line);
            return array_map(
                function ($field) {
                    return str_replace('!!Q!!', '"', utf8_decode(urldecode($field)));
                },
                $fields
            );
        },
        $lines
    );
}

?>
j8ag8udp

j8ag8udp2#

PHP似乎不允许在列数据中使用换行符。不过你可以解决这个问题:

$row = '7;"Hi'.PHP_EOL.'";3'; 
$row=str_replace(PHP_EOL,"\0",$row); 
$array = str_getcsv($row,"\n",'"');
$array = array_map(function ($v) {
   return str_replace("\0",PHP_EOL,$v);
},$array);
print_r($array);

Array
(
    [0] => 7;"Hi
";3
)
mepcadol

mepcadol3#

正在处理
php -v PHP 5.6.30(客户端)(内部版本:2017年2月7日16:18:37)

php > $row = "\"abc\"\n;\"def\"\n;\"123\"";
php > $array = str_getcsv($row,"\n",'"');
php > print_r($array);
Array
(
    [0] => abc
    [1] => ;"def"
    [2] => ;"123"
)

且这

php > $row = "\"abc\"\n\"def\"\n\"123\"";
php > 
php > 
php > $array = str_getcsv($row,"\n",'"');
php > print_r($array);
Array
(
    [0] => abc
    [1] => def
    [2] => 123
)

等等(所有其它情况)。
在var语句的分隔符中是否有其他符号,以区别于\n、\r或\r\n?

nqwrtyyt

nqwrtyyt4#

我做错了什么?
您使用错误的参数调用了函数...
http://php.net/manual/en/function.str-getcsv.php
定界符
设置字段分隔符(仅限一个字符)。
第二个参数是 field 分隔符,即;,而不是换行符。

$rows = '7;"Hi
";3';
$array = str_getcsv($rows,';','"');
var_dump($array);

// output:
array(3) {
  [0]=>
  string(1) "7"
  [1]=>
  string(4) "Hi
"
  [2]=>
  string(1) "3"
}

编辑:
结果应该是只有一个值的数组
为什么是一个值?这里实际的字段分隔符应该是什么?我假设它是;...但是如果您希望从显示的示例输入中只获得一个值,那么分隔符是什么?或者它怎么会是CSV...?

第二次编辑:

首先我需要获取行-字段分隔符是换行符
这并不是str_getcsv的工作方式--它假设您已经有了 * 一行 * CSV数据作为输入字符串。而且您不能真正使用类似于换行符处的简单爆炸来“获取”单行-- * 因为 * 换行符也可以在字段内部。
fgetcsv将是实现这两种功能的合适函数...但它操作的是文件,而不是字符串数据。也许PHP的各种流可以在某种程度上帮助实现这一点,如果您将字符串数据“写入”临时文件或内存,这样您就可以实际使用fopen来获得fgetcsv可以处理的可读流...这个问题可以给予您了解这是如何工作:how to use fgetcsv with strings

c9qzyr3d

c9qzyr3d5#

请改用fgetcsv。这个方法会行程以引号括住的新行。您也可以使用字串来建立资源。

$stream = fopen('data://text/plain,' . $csv, 'r');
        $rows = [];
        while (($row = fgetcsv($stream)) !== false) {
            $rows[] = $row;
        }
        
        var_dump($rows)

相关问题