Text::CSV vs. Text:ParseWords
Text::CSV vs. Text:ParseWords
am 21.03.2006 19:30:31 von t_pot
Ich habe mir zur Bearbeitung von CSV-Files das Modul /Text:CSV/
installiert. Das nimmt, soweit ich das übersehe, das _CSV_ allerdings
sehr wörtlich, sprich: Es ist auf Komma als Delimiter fest verdrahtet.
In meinen Files ist aber Semikolon der Delimiter. Bevor ich es jetzt mit
/Text:CSV_XS/ versuche: Kann ich mich nicht auch mit /Text::ParseWords/
aus der Affäre ziehen? Ich will ja nur erreichen, daß eventuelle
Semikola zwischen den " nicht angefasst werden, so daß wirklich nur die
Datenfelder ins Array geschoben werden.
Beispiel:
[...]
@fields = "ewords (";",1,$_);
$_ = join (";", @fields);
[...]
macht aus: /"Meier"; Mue;ller";"Schulze"/
exakt wieder dasselbe.
Bin ich damit auf der sicheren Seite?
TIA,
--
Thomas Pothmann
PGP-Key on demand
Re: Text::CSV vs. Text:ParseWords
am 21.03.2006 19:43:17 von Christian Garbs
Mahlzeit!
Thomas Pothmann wrote:
> Beispiel:
>
> [...]
> @fields = "ewords (";",1,$_);
> $_ = join (";", @fields);
> [...]
>
> macht aus: /"Meier"; Mue;ller";"Schulze"/
>
> exakt wieder dasselbe.
Die Frage ist doch: Wie sieht es zwischendurch aus? Ist @fields so
eingeteilt, wie Du das gerne hättest oder nicht?
Die ungerade Anzahl von Anführungszeichen in Deinem Beispiel gibt mir
schon mal zu denken: Wie _soll_ das denn richtig geparst aussehen?
GruÃ,
Christian
--
sub _{print"\n"}_;for(;$s<9;++$s){$_='1E2018201E00001E2018201E00001E2018201'
..'E002020001C2222221400005CA2A2A27C02001C2222221C20003E0402 02201F2422221C00'
..'242A2A2A12002020001C2222221F20001C2A2A2A0C';while(s;(..); ;){printf'%c',hex
$1&1<<$s?40:32}_}$_=':::Christian Garbs:',y;:;\t;;print;_;_
Re: Text::CSV vs. Text:ParseWords
am 21.03.2006 20:16:15 von t_pot
Christian Garbs wrote:
>Mahlzeit!
Mahlzeit! ;o)
>> macht aus: /"Meier"; Mue;ller";"Schulze"/
>>
>> exakt wieder dasselbe.
>Die Frage ist doch: Wie sieht es zwischendurch aus? Ist @fields so
>eingeteilt, wie Du das gerne hättest oder nicht?
Die Datensätze sind halt so aufgebaut, daß alle Felder mit /"/ eingefasst
sind und durch ein Semikolon getrennt werden. Ausnahme: die
Postleitzahl; die hat keine Quotes d'rumherum. Leere Felder sind einfach
durch /;/ repräsentiert. Was ich erreichen will, ist sicherzustellen, daß
nicht bei evtl. einem /;/ in Datenfeldern geparst wird.
>Die ungerade Anzahl von Anführungszeichen in Deinem Beispiel gibt mir
>schon mal zu denken: Wie _soll_ das denn richtig geparst aussehen?
Sorry, Typo. ;-) Sind - wie gesagt - überall _Tüttelchen_ d'rum, bei der
PLZ halt nicht.
--
Thomas Pothmann
PGP-Key on demand
Re: Text::CSV vs. Text:ParseWords
am 22.03.2006 16:36:48 von Volker Pohlers
ich hab meine eigene Routine für solche Fälle:
delimiter ist das Trennzeichen, quotechar optional.
sub splitline {
# We will be testing undef strings
no warnings;
use re 'taint'; # if it's tainted, leave it as such
my($delimiter, $quotechar, $line) = @_;
$quotechar ||= '×'; # 25.08.2003 09:57 hack
$delimiter =~ s/(\$|\||\^)/\\$1/g;
my($quote, $quoted, $unquoted, $delim, $word, @pieces);
while (length($line)) {
($quote, $quoted, undef, $unquoted, $delim, undef) =
$line =~ m/^($quotechar) # a $quote
((?:\\.|(?!\1)[^\\])*) # and $quoted text
\1 # followed by the same quote
([\000-\377]*) # and the rest
| # --OR--
^((?:\\.|[^\\$quotechar])*?) # an $unquoted text
#(\Z(?!\n)|(?-x:$delimiter)|(?!^)(?=["']))
(\Z(?!\n)|(?-x:$delimiter))
# plus EOL, delimiter,
or quote
([\000-\377]*) # the rest
/x; # extended layout
return(@pieces) unless( $quote || length($unquoted) || length($delim));
$line = $+;
{
$unquoted =~ s/\\(.)/$1/g;
if (defined $quote) {
$quoted =~ s/\\(.)/$1/g if ($quote eq '"');
$quoted =~ s/\\([\\'])/$1/g if ($quote eq "'");
}
}
$word .= defined $quote ? $quoted : $unquoted;
if (length($delim)) {
push(@pieces, $word);
undef $word;
}
if (!length($line)) {
push(@pieces, $word);
}
}
return(@pieces);
}
Gruß
Volker
Re: Text::CSV vs. Text:ParseWords
am 22.03.2006 22:29:16 von Christian Garbs
Mahlzeit!
Thomas Pothmann wrote:
> Die Datensätze sind halt so aufgebaut, daà alle Felder mit /"/
> eingefasst sind und durch ein Semikolon getrennt werden. Ausnahme:
> die Postleitzahl; die hat keine Quotes d'rumherum. Leere Felder sind
> einfach durch /;/ repräsentiert. Was ich erreichen will, ist
> sicherzustellen, daà nicht bei evtl. einem /;/ in Datenfeldern
> geparst wird.
Wie wäre es hiermit?
#!/usr/bin/perl -w
use strict;
sub split_csv($)
{
my ($line, $instring, $string, @fields) = (shift, 0, '');
foreach my $token ( split /([\";])/, $line ) {
if ($token eq '"') {
$instring = 1-$instring;
} elsif ($token eq ';') {
if ($instring) {
$string .= $token;
} else {
push @fields, $string;
$string = '';
}
} else {
$string .= $token;
}
}
push @fields, $string;
return @fields;
}
my $line = '"ha;llo";"Du";"da";;234;drüben;"!"';
print join("\n", split_csv($line))."\n";
Einziger offensichtlicher Nachteil: Man kann mit \" keine richtigen
Entenlatschen in ein Feld zwischen die "" schmuggeln.
GruÃ,
Christian
--
sub _{print"\n"}_;for(;$s<9;++$s){$_='1E2018201E00001E2018201E00001E2018201'
..'E002020001C2222221400005CA2A2A27C02001C2222221C20003E0402 02201F2422221C00'
..'242A2A2A12002020001C2222221F20001C2A2A2A0C';while(s;(..); ;){printf'%c',hex
$1&1<<$s?40:32}_}$_=':::Christian Garbs:',y;:;\t;;print;_;_
Re: Text::CSV vs. Text:ParseWords
am 24.03.2006 17:23:38 von t_pot
Volker Pohlers wrote:
>ich hab meine eigene Routine für solche Fälle:
>delimiter ist das Trennzeichen, quotechar optional.
[code snipped]
Weia! Da brauche ich ja 'ne Woche, bis ich das durchgeackert habe... ;o)
Trotzdem danke für den Tip. Ist abgespeichert.
So far,
--
Thomas Pothmann
PGP-Key on demand
Re: Text::CSV vs. Text:ParseWords
am 24.03.2006 17:27:15 von t_pot
Christian Garbs wrote:
>Wie wäre es hiermit?
[code snipped]
Und auch dir besten Dank. Hab's abgespeichert und werde mich
durchwühlen.
>Einziger offensichtlicher Nachteil: Man kann mit \" keine richtigen
>Entenlatschen in ein Feld zwischen die "" schmuggeln.
Ähmm... Frage: Was sind denn /Entenlatschen/?
So far,
--
Thomas Pothmann
PGP-Key on demand
Re: Text::CSV vs. Text:ParseWords
am 24.03.2006 21:40:45 von Christian Garbs
Mahlzeit!
Thomas Pothmann wrote:
> Ãhmm... Frage: Was sind denn /Entenlatschen/?
Entenlatschen == GänsefüÃchen == double quotes
GruÃ,
Christian
--
sub _{print"\n"}_;for(;$s<9;++$s){$_='1E2018201E00001E2018201E00001E2018201'
..'E002020001C2222221400005CA2A2A27C02001C2222221C20003E0402 02201F2422221C00'
..'242A2A2A12002020001C2222221F20001C2A2A2A0C';while(s;(..); ;){printf'%c',hex
$1&1<<$s?40:32}_}$_=':::Christian Garbs:',y;:;\t;;print;_;_