Thread CSV Feldlänge bestimmen (16 answers)
Opened by sara456 at 2014-05-23 16:54

topeg
 2014-05-26 12:24
#175742 #175742
User since
2006-07-10
2611 Artikel
BenutzerIn

user image
more (27.7kb):
Code (perl): (dl )
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
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
#!/usr/bin/perl
use strict;
use warnings;

my $format_file = 'format.csv';
my $data_file = 'data.csv';
my $out_file = 'data_out.csv';

# definiere die Möglichen Formate
# die einträge sind:
# - check  : Prüfung des Datensatzes gibt 1 oder 0 zurück
# - force  : Entfernen aller unerlaubten zeichen, fibt den veränderten String zurück
# - format : Formatieren des Datensatzes, gibt den formatieren String zurück
my %known_format_types=(
  'Alphanumerisch' => {
    check  => sub{ return $_[0] =~ /^[a-z0-9]*$/is?1:0 },
    force  => sub{ $_[0] =~ s/[^a-z0-9]+//igs; return $_[0]  },
    format => sub{
      my ($data,$length)=@_;
      return sprintf('%-'.$length.'s',$data);
    },
  },
  'Numerisch' => {
    check => sub{ return $_[0] =~ /^\d*$/is?1:0 },
    force => sub{
      my ($data) = @_;
      $data =~ s/\D+//igs;
      return $_[0] if($data);
      return 0;
    },
    format => sub{
      my ($data,$length)=@_;
      return sprintf('%0'.$length.'u',$data);
    },
  },
);

my $format = load_format($format_file);

# Ein- und Ausgabe öffnen
open(my $fhi, '<:encoding(UTF-8)', $data_file) or die("ERROR OPEN $data_file ($!)\n");
open(my $fho, '>:encoding(UTF-8)', $out_file) or die("ERROR OPEN $out_file ($!)\n");
# alle Daten durch gehen
while(my $line = <$fhi>) {

  # zeilenende entfernen
  chomp($line);

  # Zeile zerlegen
  my @data=split(/;/, $line);
  my @outd;

  # Daten duchgehen
  for my $pos (0 .. $#data) {

    # Wenn keine Formatangabe vorhanden ist, Spalte überspringen.
    next unless( $format->[$pos] );

    # Informationen zur Formatierung über diese Zeile holen.
    my $type   = $format->[$pos]->{type};
    my $length = $format->[$pos]->{length};
    my $pos_out= $format->[$pos]->{position};
    my $code   = $known_format_types{$type};

    # Wenn kein Code vorhanden ist, Splate überspringen.
    unless( $code ) {
      warn("ERROR Unkannter Typ für Zeile $. Spalte $pos\n");
      next();
    }

    my $result = $data[$pos];

    # Daten prüfen
    warn("WARN Fehlerhaftes Format $type für Zeile $. Spalte $pos |[$result]|\n") unless( $code->{check}->($result) );

    # Daten säubern
    $result = $code->{force}->($result);

    # Daten formatieren
    $result = $code->{format}->($result,$length);

    # Daten zurück schreiben
    $outd[$pos_out] = $result;
  }

  # Zeile in Ausgabe schreiben
  print $fho join(';',@outd).$/;
}

close($fhi);
close($fho);

########################################################################
# FUNKTIONEN
########################################################################

sub load_format {
  my ($file) = @_;
  my @data;
  open(my $fh, '<:encoding(UTF-8)', $file) or die("ERROR OPEN $file ($!)\n");

  # ignoriere erste zeile:
  <$fh>;

  while(my $line = <$fh>) {

    # Entferne Zeilenende
    chomp($line);

    # zerlege Zeile
    my @d = split(/\s+/,$line);

    # prüfe format
    die("FORMAT ERROR Zeile $. ($file) |[$line]|\n") if(@d < 3);
    die("FORMAT ERROR Zeile $. spalte 1 ($file) |[$d[0]]|\n") if($d[0]=~/\D/);
    die("FORMAT ERROR Zeile $. spalte 2 ($file) |[$d[1]]|\n") if($d[1]=~/\D/);
    die("FORMAT ERROR Zeile $. spalte 3 ($file) |[$d[2]]|\n") if($d[2]=~/\D/);

    # setze Datensatz ein
    $data[$d[0]-1] = {position => $d[1]-1, length => $d[2], type => $d[3]};
  }
  close($fh);

  return \@data;
}

View full thread CSV Feldlänge bestimmen