[php] string splitten op komma's maar niet tussen quotes

Pagina: 1
Acties:

Onderwerpen


Acties:
  • 0 Henk 'm!

  • schizofreen
  • Registratie: Juni 2000
  • Laatst online: 19-09 13:22
ik zit met het volgende probleem:

ik import een CSV file en ga wil daarna regel voor regel doorlopen door ieder element in een array te plaatsen, een regel ziet er dan bijvoorbeeld zo uit:

eerste,tweede,derde,"dit is, de vierde",vijfde

als ik explode gebruik en laat scheiden op de komma zal het vierde element gesplitst worden, maar dat wil ik juist niet. Iets zegt mij dat ik een functie als preg_split zou moeten gebruiken, maar ik weet niet hoe.

laat ik nou toevallig toch een stift bij me hebben! - specs


Acties:
  • 0 Henk 'm!

  • schizofreen
  • Registratie: Juni 2000
  • Laatst online: 19-09 13:22
lijkt idd veel op mijn probleem, maar lost het toch niet op.
In dat topic gaat het ook om extra haakjes om het geheel, daar heb ik niets mee te maken, ik wil alleen een array op basis van elementen

laat ik nou toevallig toch een stift bij me hebben! - specs


Acties:
  • 0 Henk 'm!

  • NMe
  • Registratie: Februari 2004
  • Laatst online: 09-09 13:58

NMe

Quia Ego Sic Dico.

Ik denk dat je beter kan gaan tokenizen.

'E's fighting in there!' he stuttered, grabbing the captain's arm.
'All by himself?' said the captain.
'No, with everyone!' shouted Nobby, hopping from one foot to the other.


  • R4NCOR
  • Registratie: December 2000
  • Laatst online: 16-09 12:26

R4NCOR

eigenlijk gewoon Niels

Toegegeven, ik heb slechts beperkte kennis en los daarom problemen vaak op met een workaround die wellicht veel efficienter kunnen... Maar goed:

Je zou eerst kunnen splitten op quotes ("). Daarna doorloop je de array, waarvan je de elementen op komma's gaat splitten. Behalve de elementen die tussen de quotes inzitten. In het geval van gebruik van explode() bijvoorbeeld, zijn alle oneven elementen dan elementen die tussen quotes zitten...

zoiets dus:

PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
$blaat = "eerste,tweede,derde,\"dit is, de vierde\",vijfde";


$quotes = explode("\"", $blaat);
for ($i = 0; $i < count($quotes); $i++) {
    if (($i % 2) == 0) {
        $commas = explode(",", $quotes[$i]);
        foreach ($commas as $value) {
            if ($value != $null) { $array[] = $value; }
        }
        if ($i < (count($quotes) - 1)) {$array[] = $quotes[$i+1]; }
    }
}

print_r($array);


Geeft als output:

code:
1
2
3
4
5
6
7
8
Array
(
    [0] => eerste
    [1] => tweede
    [2] => derde
    [3] => dit is, de vierde
    [4] => vijfde
)


Voorwaarde hieraan is echter wel dat er geen losse quotes in mogen staan, dus ze moeten altijd zo'n uitzondering aankondigen..
Anyway, like said before, kan vast efficienter en/of beter :) Probeer mee te denken :*

  • beetle71
  • Registratie: Februari 2003
  • Laatst online: 09-09 15:24
Misschien een tip: Als je dit gebruikt om een CSV file te parsen kun je ook eens kijken naar de FGETCSV functie van php

[ Voor 3% gewijzigd door beetle71 op 24-02-2005 07:38 ]


  • schizofreen
  • Registratie: Juni 2000
  • Laatst online: 19-09 13:22
de oplossing die ik uiteindelijk gevonden heb lijkt op dei van R4NCOR, op een forumpje vond ik dit:

PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
function csv_explode($str, $delim = ',', $qual = "\""){
    $len = strlen($str);
    $inside = false;
    $word = '';
    for ($i = 0; $i < $len; ++$i) {
        if ($str[$i]==$delim && !$inside) {
            $out[] = $word;
            $word = '';
        } else if ($inside && $str[$i]==$qual && ($i<$len && $str[$i+1]==$qual)) {
            $word .= $qual;
            ++$i;
        } else if ($str[$i] == $qual) {
            $inside = !$inside;
        } else {
            $word .= $str[$i];
        }
    }
    $out[] = $word;
    return $out;
}

laat ik nou toevallig toch een stift bij me hebben! - specs


Verwijderd

Deze oplossing zou ook kunnen:
PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
    $string = 'eerste,tweede,derde,"x,xx",vijfde';
    $aResult = $aTmp = array();
    $offset = 0;
    $string = ' '.$string;
    while( $p1 = strpos( $string, '"', $offset ) ){
        if( !$p2 = strpos( $string, '"', $p1+1 ) ) break;   
        $count = substr_count( substr($string, 0, $p1 ), ',' );
        $val = substr( $string, $p1, ($p2+1)-$p1 );
        $aTmp[] = array('key'=>$count,'val'=>$val);
        $string = str_replace( $val, null, $string );
        $offset = $p1;
    }
    $string = substr( $string, 1 );
    $aResult = explode( ',', $string );
    while( list($k,$v) = each($aTmp) )
        $aResult[$v['key']] = $v['val'];
//  print_r($aResult);

:9

  • J27
  • Registratie: Januari 2003
  • Nu online

J27

om je misschien toch weer even op weg te helpen met regular expressions, dit voorbeeldje:

code:
1
2
3
Regex  re = new Regex(",(?=(?:[^\"]*\"[^\"]*\")*(?![^\"]*\"))");
line = myFile.ReadLine(;
re.Split(line);


dit gebruik ik in c# om een csv file uit te lezen (readline staat eigenlijk in een loopje)
voorbeeldregel van wat deze regex kan splitten:

"waarde1, met komma", waarde2, "waarde3"

edit: ik neem aan dat deze code niet moelijk te vertalen is naar PHP
misschien kun je gewoonpreg_split gebruiken met als regular expression:
",(?=(?:[^\"]*\"[^\"]*\")*(?![^\"]*\"))"

[ Voor 46% gewijzigd door J27 op 24-02-2005 14:20 ]


  • Michali
  • Registratie: Juli 2002
  • Laatst online: 29-05 22:54
Dit kan ook (vrij simpele oplossing):
PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
<?

$string = 'item1,item2,"item3,item4","item5",item6';

$split = explode(",", $string);

$output = array();
$index = 0;
$open = false;

foreach ( $split as $item )
{
    if ( ( strpos($item, '"') !== false ) &&
        ( substr_count($item, '"') % 2 != 0 ) )
    {
        if ( $open )
        {
            $output[$index++] .= "," . $item;
        }
        else
        {
            $output[$index] = $item;
        }
        
        $open = !$open;
    }
    else
    {
        if ( $open )
        {
            $output[$index] .= "," . $item;
        }
        else
        {
            $output[$index++] = $item;
        }
    }
}

var_dump($output);

?>

[ Voor 11% gewijzigd door Michali op 24-02-2005 16:27 ]

Noushka's Magnificent Dream | Unity

Pagina: 1