Zeichen aus Liste zählen und in Tabelle schreiben

Hi,



ja genau - und weil gesagt wird, dass das Substitut gelöscht werden soll, bin
ich beim näheren nachdenken total durcheinander gekommen - ganz offensicht-
lich werden die anderen Zeichen ja hinterher doch gezählt ... wo kommen die
denn dann her, wenn sie vorher rausgeschmissen werden :hilfe2:

Du musst Dir vor Augen halten, wie substitute (s//) funktioniert. Der Perl-Interpreter nimmt sich jedes einzelne Zeichen des Textes vor und prüft, ob er auf das erste Zeichen des Suchmusters passt. Bei Erfolg nimmt er das nächste Zeichen dazu und prüft, ob diese beide Zeichen auf das Suchmuster passt. Wenn nein, geht er zum nächsten Zeichen und fängt wieder mit der Prüfung an. Wenn er nun eine Zeichenfolge gefunden hat, die auf das Muster passt (ich lass jetzt mal greedy aussen vor), dann nimmt er diese und ersetzt sie entsprechend. Dieses Überprüfen in unserem Beispiel funktioniert nun folgendermassen:

Code:
bsp                  (?<!a):   |   [^\w\@:]   Ersetzen (und damit Löschen)
: (mit a davor)         0             0                    nein
: (mit b davor)         1             0                     ja
@                       0             0                    nein
%                       0             1                     ja
a                       0             0                    nein

Aber gut ...
...
[*]... die Problemfälle (also Kombinationen, welche als ein Zeichen gelesen/gezählt werden müssen) sind:
Code:
ts
a:
E:
aI
aU 
OI
@6
Y6
96
U6
O6
a6
I6
E6
26
E:6

Leider ist bei so vielen Kombinationen die Split-Methode nicht mehr ratsam. Besser wäre:

Code:
perl -0777 -ne '
	@l = ("E:6","ts","a:","E:","aI","aU","OI","\@6","Y6","96","U6","O6",
              "a6","I6","E6","26",("a".."z"),("A".."Z"),(0..9));
	foreach $l (@l) {print "$l\t$n\n" if $n=$_=~s/$l//g}
' testtext

Ich hab die Zeile für bessere Lesbarkeit umgebrochen.

Gruss, Xanti
 
Zuletzt bearbeitet:
Hallo

Noch ein paar Erklärungen auf die schnelle, die du eventuell noch brauchen könntest.

$h{$_}++ for split /(?!:)/,$_;

Das sieht schlimmer aus als es ist. ;)
Fangen wir vonHinten an, was bei perl nicht ungewöhnlich ist.
Funktion split liefert eine Liste, indem $_ (der Wert nach dem Komma) in einzelne Elemente zerlegt wird.
Als Argumente kennt split in dieser Form hier einen regulären Ausdruck und den zu splittenden String.
Split kennt noch mehr Formen, die ich aber hier mal weglasse. perldoc -f split ;)
Dabei wird das Matching auf den REGEXP als Delimiter betrachtet.
Kurze Erläuterung zu Regexp -> siehe auch Hier Achte auf das Lookahead!
for erwartet eine Liste, die wir gerade von split bekommen.
In Perl kann man die Bedingungen auch sozusagen hinterherwerfen. ;)
Wir könnten auch andersrum schreiben:
for (split /(?!:)/,$_){$h{$_}++}
Nun zum
h ist hier ein hash und würde in einem ordentlichen Perlscript so declariert:
Ein Hash ist ein Array, welches nicht per Indexnummer initialisiert wird, sondern per Namen. Jedes Element hat einen Namen, auf welches ich im scaleren Kontext so zugreife:
$hashname{Elementname}=Wert
In unserem Fall benutze ich jeden einzelnen Buchstaben (steht ja in $_ in der for Schleife), als Name und addiere 1 dazu.($var++ ist das Gleiche wie $var= $var + 1);
Steht also in $_ ein a, dann wird dem Wert $h{a} 1 dazugezählt. Das ist der eigentliche Counter.
print "$_= $h{$_}\n"
Printet übrigens einfach "Buchstabe = Zählwert" aus, hier wird das = also nicht als Zuweisung genommen, sondern wirklich als Zeichen ausgegeben. Ist nur Kosmetik und könnte auch durch Tabulator oder andere Zeichen ersetzt werden.

Hoffe es hilft ein wenig zu verstehen.

Gruß Wolfgang
 
Zurück
Oben