我有一个关于将CSV字符串转换为数组的问题。
INV;165;1;0;1 Username;0;10000;"Here is multiline-text.
with line-breaks:
";20 Offen;0,00
INV;166;1;0;1 Username2;0;10000;"Here is another multiline-text.
with line-breaks:
";20 Offen;0,00我试图用str_getcsv拆分字段,但问题是,分隔符只出现在一个字段中,并且该函数还拆分了多行字段。
我的解决方案是首先通过preg_replace转换换行符,但我不会深入讨论它。下面是我的正则表达式,它只替换由;“和”括起来的换行符:
/(;")(.*)(\n)(.*)(";)/这个模式实际上只匹配第一个换行符。有谁能给我一个做这项工作的提示吗?
提前谢谢你。
以下是原始的CSV:
CMXINV;165;1;0;1 Felix Hirschberg;0;10000;Herr;;Max;Muster;Company;;Street;123;City;DE;(0 40) 6 25 6;;(0 40) 6 25 6;mail@muster.de;;;;;;;;0;20121217;20121217;1 Sofort ohne Abzug;EUR;1 Agentur;0 ;0,00;;"Vielen Dank für Ihren Auftrag.
Vereinbarungsgemäß berechnen wir Ihnen:
";"Mit besten Grüßen
Invoice Man";;0;0;0;0;;20 Offen;0,00;;0 ;0,00;0,00;;EXW;;;;;;;;;;;;;;;;2;;Project: Test-Project;;0,000;0,00;1,000;0,00;0,00;0;0;0;0;0
CMXINV;165;2;0;1 Felix Hirschberg;0;10000;Herr;;Max;Muster;Company;;Street;123;City;DE;(0 40) 6 25 6;;(0 40) 6 25 6;mail@muster.de;;;;;;;;0;20121217;20121217;1 Sofort ohne Abzug;EUR;1 Agentur;0 ;0,00;;"Vielen Dank für Ihren Auftrag.
Vereinbarungsgemäß berechnen wir Ihnen:
";"Mit besten Grüßen
Invoice Man";;0;0;0;0;;20 Offen;0,00;;0 ;0,00;0,00;;EXW;;;;;;;;;;;;;;;;0;1;"- job1 (1h)
- job2 (1h)
- job3 (0,75h)
- job4 (1h)
- job5 (0,5h)";HR;3,25;100,00;1,00;0,00;325,00;1;0;0;0;0
MESSAGE;S;210053;INVOICE_GET hat 1 Datensätze zurückgegeben
MESSAGE;S;204020;Datenübertragung erfolgreich. Es wurden 1 Datensätze verarbeitet.发布于 2012-12-27 22:24:09
你可以试试这个:
/;"(([^"]*)([\r\n])+([^"]*))+"/im这将匹配;"分隔符中每个换行符之前和之后的文本。第二个匹配将是前面的文本,第四个匹配将是下面的文本。
请注意,我去掉了最后一个';‘,以确保如果多行值是该行中的最后一个,它仍然会匹配。
发布于 2012-12-27 23:48:38
根据用户在php手册中的评论,fgetcsv()和str_getcsv()都应该正确处理换行符。
您可能应该利用这些实现(它们应该已经解决了您可能遇到的任何可能问题)。
编辑:自己的解析器
或者您可以编写自己的解析器(基于注释):
// Browse file one character after another
while (false !== ($c = fgetc($fp))) {
// We are not inside the value, newline = new row
if( ($c == "\n") || ($c == "\r")){
// Newline, add to result
continue;
}
// Whitespace? continue, do nothing
if( ctype_space( $c)){
continue;
}
// Okay, now we can use switch
switch( $c){
case ',':
// Add empty value
break;
// Escaped value
case '"':
case "'":
$escapeChar = $c;
$prevChar = '';
$value = '';
while( false !== ($c = fgetc($fp))){
// We just hit and end of escaped sequence, check escaped val by \
if( ($c == $escapeChar) && ($c != '\\') ){
break;
}
// If we got \ and prev value is \ = "blah blah \\"
// Prevent escape escape character of being guessed incorrectly
if( ($c == '\\') && ($prevChar == '\\')){
$prevChar = '';
} else {
$prevChar = $c;
}
$value .= $c;
}
// $value is your value
break;
// Normal, non escaped value:
default:
$value = '';
while( false !== ($c = fgetc($fp))){
if( ($c == ',') || ($c == '\n') || ($c == '\r')){
break;
}
$value .= $c;
}
// $value = your field value
break;
}
}发布于 2012-12-28 00:38:50
如果在文件中有CSV输入,那么可以只使用fgetcsv(),它可以很好地处理多行输入。
如果CSV输入是字符串,则可以使用特殊的php://temp I/O流将其高效地传递给fgetcsv()
$fp = fopen( 'php://temp', 'w+' );
fputs( $fp, $csv );
rewind( $fp );
$data = fgetcsv( $fp, 0, ';', '"' );
fclose( $fp );https://stackoverflow.com/questions/14055705
复制相似问题