Thread Zeilenzahl bestimmen bei veränderten Seperator
(21 answers)
Opened by manu at 2012-08-01 13:58
Bedenke für einen Computer gibt es keine Zeilen in dem sinne. Es das wie wir es interpretieren. Wenn du sagst "/>" soll das ende einer sein dann ist das für Perl auch so.
Wenn du wissen willst in welcher "\n"-Zeile ein Wert, ist aber anders parsen willst musst du das passend Programmieren Ein Ansatz: 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 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 #!/usr/bin/perl use strict; use warnings; use XML::Parser; use Data::Dumper; use IO::File; my $file='test.out.xml'; my $tree={ type => 'root', name => 'root', values =>{}, line_start => 0, line_end => 0, childs => [], }; my @deep=($tree); my $xmlp = XML::Parser->new( Handlers => { # Datei öffenen beim starten des Parsens Init => sub{ my $parser=shift; # den Dateinamen aus dem Parser-Objekt holen my $fh = IO::File->new($parser->{Base}, 'r') or die( "Error open $parser->{Base} ($!)\n" ); # einen Eintrag im Parser für das Filehandle machen $parser->{__MY__FH__}={fh => $fh, lastline=>$fh->getline()}; }, # tag start Start => sub{ my $parser=shift; my $name=shift; my %values=@_; my $line=test_line($parser->{__MY__FH__},"<$name"); my $element={ type => 'tag', name => $name, values => \%values, line_start => $line, line_end => $line, childs => [], }; push(@{$deep[-1]->{childs}},$element); push(@deep,$element); }, # tag end End => sub{ my $parser=shift; my $name=shift; my $line=test_line($parser->{__MY__FH__},">"); if(@deep > 1) { my $element=pop(@deep); $element->{line_end}=$line; } }, # Strings zwischen tags Char => sub{ my $parser=shift; my $string=shift; # an vorhandenen String anhängen if(@{$deep[-1]->{childs}} && $deep[-1]->{childs}->[-1]->{type} eq 'char') { $deep[-1]->{childs}->[-1]->{childs}.=$string; return; } # ignoriere "\n" und leere Zeilen if($string=~/\s*/s) { if(@{$deep[-1]->{childs}} && $deep[-1]->{childs}->[-1]->{type} eq 'char') { $deep[-1]->{childs}->[-1]->{line_end}++ while($string=~/[\x0a\x0d]/gc); } return; } my $line=test_line($parser->{__MY__FH__},$string); my $element={ type => 'char', name => '', values =>{}, line_start => $line, line_end => $line, childs => $string }; push(@{$deep[-1]->{childs}},$element); }, }); $xmlp->parsefile($file); print Dumper($tree); ######################################################################## sub test_line { my $fh=shift; my $string=shift; my $line=-1; # ist es in der letzten gelesenen Zeile? my $pos=index($fh->{lastline},$string); my $tell=$fh->{fh}->tell(); if($pos >= 0) { # schon gefundenes löschen substr($fh->{lastline},0,$pos+length($string),''); #aktuelle Zeilennummer $line=$fh->{fh}->input_line_number(); } else { # Datei weiter einlesen bis gefunden while($fh->{lastline}=$fh->{fh}->getline()) { my $pos=index($fh->{lastline},$string); if($pos >= 0) { # schon gefundenes löschen substr($fh->{lastline},0,$pos+length($string),''); #aktuelle Zeilennummer $line=$fh->{fh}->input_line_number(); last; } } } # zurück zu letzer position wenn nicht gefunden $fh->{fh}->seek($tell,0) if($line == -1); return $line; } |