Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/252.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
PHP中解析CSV的正则表达式_Php_Regex_Csv - Fatal编程技术网

PHP中解析CSV的正则表达式

PHP中解析CSV的正则表达式,php,regex,csv,Php,Regex,Csv,我已经使用以下正则表达式成功拆分了CSV文件: “/,(?=(?:[^\“]\”[^\“]\”(![^\“]\”)/” 但我最终得到了一个字符串数组,其中包含开头和结尾的双引号。 现在我需要一个正则表达式,它可以去掉这些字符串中的分隔符双引号 据我所知,CSV格式可以将字符串封装在双引号中,并且已经是字符串一部分的所有双引号都是双引号。例如: 我的“另一只”猫 变成 我的“另一只”猫 我基本上需要的是一个正则表达式,它将所有N个双引号序列替换为一个(N/2-向下舍入)双引号序列 还是有更好的办法

我已经使用以下正则表达式成功拆分了CSV文件: “/,(?=(?:[^\“]\”[^\“]\”(![^\“]\”)/”

但我最终得到了一个字符串数组,其中包含开头和结尾的双引号。 现在我需要一个正则表达式,它可以去掉这些字符串中的分隔符双引号

据我所知,CSV格式可以将字符串封装在双引号中,并且已经是字符串一部分的所有双引号都是双引号。例如:

我的“另一只”猫

变成

我的“另一只”猫

我基本上需要的是一个正则表达式,它将所有N个双引号序列替换为一个(N/2-向下舍入)双引号序列

还是有更好的办法?
提前感谢。

这里是我的快速尝试,尽管它只适用于单词边界

preg_replace('/([\W]){2}\b/', '\1', $csv)

有读取csv文件的功能:

既然有fgetcsv功能为您完成所有繁重的工作,为什么还要麻烦用regex分割文件


您可以传入分隔符和分隔符,它将检测要执行的操作。

我同意其他人的看法,他们说您应该使用fgetcsv函数而不是regex。正则表达式可以在格式良好的CSV数据上正常工作,但如果CSV格式错误或损坏,正则表达式将自动失败,可能会在过程中返回虚假结果

然而,这个问题是关于在初始拆分后去掉不需要的引号的。目前提出的一种解决方案太幼稚了,它只处理字段内的转义引号,而不是实际的分隔符。(我知道OP没有询问这些问题,但它们确实需要删除,所以为什么不将它们与其他人一起删除?)以下是我的解决方案:

$csv_field = preg_replace('/"(.|$)/', '\1', $csv_field);

此正则表达式匹配引号,后跟任何字符或字符串末尾,并用第二个字符替换匹配的字符,如果匹配的是
$
,则用空字符串替换匹配的字符。根据规范,CSV字段可以包含行分隔符;这似乎不太常见,但如果需要,您可以在正则表达式中添加“s”修饰符。

对于不想使用正则表达式而不是fgetcsv的人。下面是一个完整的示例,说明如何使用正则表达式从csv创建html表

    $data = file_get_contents('test.csv');
    $pieces = explode("\n", $data);

    $html .= "<table border='1'>\n";
    foreach (array_filter($pieces) as $line) {

            $html .= "<tr>\n";
            $keywords = preg_split('/,(?=(?:[^\"]*\"[^\"]*\")*(?![^\"]*\"))/', $line,-1,PREG_SPLIT_DELIM_CAPTURE);

            foreach ($keywords as $col) {
                    $html .= "<td>".trim($col, '"')."</td>\n";
            }
            $html .= "</tr>\n";
    }
    $html .= "</table>\n";
$data=file\u get\u contents('test.csv');
$pieces=分解(“\n”,$data);
$html.=“\n”;
foreach(数组_过滤器($个)作为$行){
$html.=“\n”;
$keywords=preg\u split('/,(?=(?:[^\“]*\”[^\“]*\”*(?![^\“]*\”)/,$line,-1,preg\u split\u DELIM\u CAPTURE);
foreach($col形式的关键字){
$html.=''.trim($col','')。“\n”;
}
$html.=“\n”;
}
$html.=“\n”;
与“玩具”或“我们”等字符串的内部存在问题

因此,你应该使用:

preg_split('/'.$seperator.'(?=(?:[^\"])*(?![^\"]))/', $line,-1, PREG_SPLIT_DELIM_CAPTURE);

是的,尽管CSV格式很简单,但用正则表达式处理它却令人恼火。如果你有一个特制的解析器,一定要使用它。+1当PHP中有一个内置函数完全满足你的需要时,你会疯狂地使用regex for CSV。是的。为什么要重新发明轮子,因为有些东西经过了很好的测试,并且可以解决您的问题。因为可能您从第三方获得了CSV导出,但该第三方没有正确引用文本字段,并且fgetcsv错误地将字符串1.15解释为值为1.1499999999的浮点。但是,最后编写一个快速脚本来修复CSV文件,然后使用fgetcsv更容易:o)fgetcsv做得不好当数据是DBCS字符(如中文)时,它将从DBCS字符中删除前缀SBCS字符。首先必须正确声明setlocale。因此,我更喜欢正则表达式解决方案这不会删除字符串周围的双引号并转换字符串中的双引号(表示为“”或“”)。因此我添加了以下代码:
array\u walk($m,create\u函数('&$item,$key','$item=str\u replace(array(\'“”,\'\'\''\'),\''''''''''''''''''''\'),trim($item,“);)),其中m是preg_split语句的结果数组(注意:由于php版本可能<5.3,我使用create_函数),这不适用于字符串中带有逗号的csv行。
preg_split('/'.$seperator.'(?=(?:[^\"])*(?![^\"]))/', $line,-1, PREG_SPLIT_DELIM_CAPTURE);