如何从PHP中删除csv中的引号

时间:2013-08-19 14:15:05

标签: php csv

我有一个从DB获取的数组。在这个项目中,我将我的数组转换为csv文件。但每次我打开文件我得到双重quoetes。我试过str_replace和preg_place没有成功。我该如何删除引号

这是我的csv代码

$query = "SELECT t.transactiontime, t.restaurant_id, t.transactionid, t.cardid, emd.m_field_id_2, t.pricebefordiscount, t.menucard_cut
from transactions as t
left join exp_member_data AS emd ON (t.cardid-10000000 = emd.member_id) order by t.transactiontime desc limit 50";

$transactions_query = ee()->db->query($query);
$transactions_result = $transactions_query->result_array();

$transaction_array = array();
foreach ($transactions_result as $key) 
{
  $date = new DateTime($key['transactiontime']);
  $newdate = $date->format('d.m.Y');


 $transaction_array[] = array(
    'transactiontime' => $newdate,
    'restaurant_id' =>  $key['restaurant_id'], 
    'member' => $key['transactionid'] . " " . $key['m_field_id_2'],
    'pricebefordiscount' => $key['pricebefordiscount']/100,
    'menucard_cut' => $key['menucard_cut']
    ); 


}


function outputCSV($data) 
    {

$outstream = fopen("php://output", 'w');



function __outputCSV(&$vals, $key, $filehandler) 
{
    fputcsv($filehandler, $vals, ';');
}

array_walk($data, '__outputCSV', $outstream);

fclose($outstream);
}

outputCSV($transaction_array);

我的输出

19.08.2013;47657;"12459 Abdullahi";60;
19.08.2013;47658;"12455 atima";30;

4 个答案:

答案 0 :(得分:2)

报价确实没有错。当一些CSV使用空格作为分隔符时,它们可以避免任何混淆:

data    "some more"    another thing
//is not the same as:
data    some more    another thing

但是,如果要删除它们,请将此正则表达式应用于每一行:

$line = preg_replace('/(^|;)"([^"]+)";/','$1$2;',$line);

你应该没事。
它是如何工作的:

  • (^|;)匹配(并捕获)行的开头或分号
  • "匹配文字"(不捕获)
  • ([^" ]+):匹配并捕获至少一个 "
  • 的字符
  • ";:匹配(不捕获)文字";
  • $1$2;$1是对第一个匹配组((^|;))的反向引用 $2引用([^";]+);只是文字

假设$line'19.08.2013;47657;"12459 Abdullahi";60;',结果(在preg_replace调用之后)将为:'19.08.2013;47657;12459 Abdullahi;60;'。报价不见了。

但是,如果某个字段包含"个字符,它可能会被转义(\"),所以为了防止正则表达式无法发现,这是一个使用前瞻的字符串断言:

$line = preg_replace('/(?<=^|;)"(.+)"(?=;)/','$1',$line);

区别:

  • (?<=^|;)一个非捕获的正面看法。模式中的下一个内容只有在字符串开头(^)或分号
  • 之前才会匹配
  • (.+)现在是第二组。它匹配所有内容,包括" BUT:
  • "(?=;)仅当"后面跟;匹配时才匹配{。}}。

当显示类似'19.08.2013;47657;"12459 \"Abdullahi\"";60;'的行时,后一个表达式将返回19.08.2013;47657;12459 \"Abdullahi\";60;&lt; - 它只删除未转义的引号

答案 1 :(得分:0)

Re write the file and try to parse csv file:

$file_path = "Book1.csv";
$string = file_get_contents($file_path, FILE_USE_INCLUDE_PATH);
echo $string;
echo "<br><br><br>";
$string2 = str_replace('"', " ", $string);
echo $string2;
file_put_contents($file_path, $string2); 
exit;

答案 2 :(得分:0)

通常有很好的理由将单元格值括在CSV的引号中。通常是因为存在危险/担心,单元格值包含列值分隔标记。解析CSV时删除它们可能会造成严重破坏。

在格式良好的CSV文件中,如果单元格用引号引起来,则需要转义构成单元格值一部分的引号。转义非常重要,否则读取CSV的解析器将无法理解单元格值的开始和结束位置。

不幸的是,会犯错误。而且您可能在这里,因为您必须在创建者未正确转义其CSV的情况下分析CSV。因此,下面是剥去外壳引号的确定方法。下面的RegEx将删除单元格值的开头和结尾的引号,但不能删除其中的引号。

$delimiter = ',';
$enclosure = '"';
$row = preg_replace("/(?:(?<=^|{$delimiter}){$enclosure})|(?:{$enclosure}(?=$|{$delimiter}))/",'',$row);

如果定界符为竖线,请确保在其前面加上2个反斜杠字符(\\|)。

可以找到一个演示here

答案 3 :(得分:-1)

试试这个

$array = array('19.08.2013',47657,'"12459 Abdullahi"');
$array = str_replace('"', '', $array);
outputCSV($array);

所以在您的代码中可能会出现这种情况

$transaction_array = str_replace('"', '', $transaction_array);

或检查此帖子

Avoid default quotes from csv file when using fputcsv

相关问题