3

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を使用してフィールドを分割しようとしましたが、問題は、区切り文字が1つのフィールドでのみ発生し、関数が複数行フィールドも分割していることです。

私の解決策は、最初に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.
4

3 に答える 3

2

これを試すことができます:

/;"(([^"]*)([\r\n])+([^"]*))+"/im

;"これは、区切り文字内のすべての改行の前後のテキストに一致します。2 番目の一致は前のテキストになり、4 番目の一致は次のテキストになります。

最後の「;」を省略していることに注意してください。複数行の値が行の最後である場合でも、これが一致することを確認します。

于 2012-12-27T14:24:08.713 に答える
1

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-27T15:48:38.413 に答える
0

ファイルにCSV入力がある場合は、を使用するだけでfgetcsv()、複数行のエントリをうまく処理できます。

CSV 入力が文字列の場合、特別なphp://tempI/O ストリームを使用して効率的に に渡すことができfgetcsv()ます。

$fp = fopen( 'php://temp', 'w+' );
fputs( $fp, $csv );
rewind( $fp );
$data = fgetcsv( $fp, 0, ';', '"' );
fclose( $fp );
于 2012-12-27T16:38:49.987 に答える