提问人:Nikhil Mohan 提问时间:10/23/2023 最后编辑:Nikhil Mohan 更新时间:10/25/2023 访问量:87
使用 PHP 解析 csv 文件中转义的逗号
Parse escaped comma in a csv file using PHP
问:
我正在尝试解析 csv 文件。但是在尝试解析以下行时,我遇到了一个转义逗号的问题。
<?php
$str = "19018216307,Public,\,k]'=system1-system2,20230914143505.5,1-050000,No";
$data = str_getcsv($str);
?>
输出:
<?php
Array
(
[0] => 19018216307
[1] => Public
[2] => \
[3] => k]'=system1-system2
[4] => 20230914143505.5
[5] => 1-050000
[6] => No
)
?>
让我们考虑列值 \,k]'=system1-system2。它应该被解析为 ,k]'=system1-system2。但是在处理 CSV 文件时,PHP 将其视为 2 列,结果类似于 \ 和 k]'=@system1-system2。
预期输出:
<?php
Array
(
[0] => 19018216307
[1] => Public
[2] => ,k]'=system1-system2
[3] => 20230914143505.5
[4] => 1-050000
[5] => No
);
?>
注意:CSV 文件是由外部网站生成的原始数据。所以我不能对csv文件内容做任何事情。(例如:将列值放在双引号中)
提前致谢!
答:
0赞
Casimir et Hippolyte
10/25/2023
#1
奇怪的“csv 格式”的解决方法:
$str = "19018216307,Public,\,k]'=system1-system2,20230914143505.5,1-050000,No";
$pattern = <<<'REGEX'
~(?nxx)
(?# modifiers:
- inline n: parenthesis act as a non-capturing group
- inline xx: white-spaces are ignored even in character classes
- global A: all the matches have to be contiguous
)
# pattern
( (?!\A) , \K | \A ) # not at the start with a commas or at the start without
[^ , \\ ]* ( \\ . [^ , \\ ]* )* # field content (all that isn't a comma nor
# a backslash, except escaped characters)
# final check
( \z (*:END) )? # define a marker if the end of the string is reached
~A
REGEX;
if (preg_match_all($pattern, $str, $m) && isset($m['MARK'])) {
$result = array_map(fn($s) => strtr($s, ['\\\\' => '\\', '\\' => '']), $m[0]);
print_r($result);
}
如果格式允许在字段中使用换行符,请添加修饰符 s.(即 在模式的末尾或开始时)~As
(?nxxs)
评论
0赞
Nikhil Mohan
10/25/2023
我对此感到担忧,我尝试了您的代码。但是,如果 csv 文件中有多行,则它不起作用。
0赞
Casimir et Hippolyte
10/25/2023
@NikhilMohan:此代码是为一行设计的(如示例中所示,因为您使用了该函数)。要使它适用于整个文件,您可以这样使用它: 3v4l.org/M7tJP#v8.2.11str_getcsv
评论
str_getcsv
system1\,system2
system1-system2
str_getcsv()