Zeilenumbruch und/oder Einzelne Strings in List zus.fügen!

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
CiveX
User
Beiträge: 34
Registriert: Samstag 23. Mai 2009, 11:48

Hallo,
ich hänge derweil an einem Tutorial fest, für Computerlinguistik.

Das Programgerüst sieht wie folgt aus:

Code: Alles auswählen

# coding=utf-8

"""
Tagging-Format umwandeln

Das Korpus aus dem vorliegenden
Format: Token\tTag.Morphologie\tLemma\n
mit einem Token pro Zeile und Leerzeilen
als Satzgrenzenmarkierung

in folgendes Format umwandeln:
Token1/Tag2 Token2/Tag2 ...
mit einem Satz pro Zeile, wobei das
Wortarten-Tag durch einen Schrägstrich
an das jeweilige Token angefügt ist
und die zusätzlichen morphologischen
Merkmale und die Lemmata nicht mit ausgegeben
werden.
"""

korpus = u"""Rund\tADJD.Pos\tRund
40\tCARD\t40
Prozent\tN.Reg.*2.*3.Neut\tProzent
aller\tPRO.Indef.Attr.-3.Gen.Pl.Neut\talle
staatlichen\tADJA.Pos.Gen.Pl.Neut\tstaatlich
Gelder\tN.Reg.Gen.Pl.Neut\tGeld
für\tAPPR.Acc\tfür
Verkehr\tN.Reg.Acc.Sg.Masc\tVerkehr
,\tSYM.Pun.Comma\t,
Gesundheit\tN.Reg.Acc.Sg.Fem\tGesundheit
und\tCONJ.Coord.-2\tund
Soziales\tN.Reg.Acc.Sg.Neut\tSoziale
würden\tVFIN.Aux.3.Pl.Past.Subj\twerden
unterschlagen\tVPP.Full.Psp\tunterschlagen
.\tSYM.Pun.Sent\t.

Die\tART.Def.Nom.Pl.Masc\tdie
dadurch\tPROADV.Dem\tdadurch
verursachten\tADJA.Pos.Nom.Pl.Masc\tverursacht
Schäden\tN.Reg.Nom.Pl.Masc\tSchaden
beliefen\tVFIN.Full.3.Pl.Past.Ind\tbelaufen
sich\tPRO.Refl.Subst.3.Acc.Pl.*6\tsie
auf\tAPPR.Auf\tauf
rund\tADJD.Pos\trund
20\tCARD\t20
Milliarden\tN.Reg.Acc.Pl.Fem\tMilliarde
Dollar\tN.Reg.*2.*3.Masc\tDollar
im\tAPPRART.Dat.Sg.Neut\tin
Jahr\tN.Reg.Dat.Sg.Neut\tJahr
.\tSYM.Pun.Sent\t.

Ein\tART.Indef.Nom.Sg.Masc\teine
Teil\tN.Reg.Nom.Sg.Masc\tTeil
der\tART.Def.Gen.Pl.Neut\tdie
unterschlagenen\tADJA.Pos.Gen.Pl.Neut\tunterschlagen
Gelder\tN.Reg.Gen.Pl.Neut\tGeld
werde\tVFIN.Aux.3.Sg.Pres.Subj\twerden
von\tAPPR.Dat\tvon
der\tART.Def.Dat.Sg.Fem\tdie
Verwaltungsmafia\tN.Reg.Dat.Sg.Fem\t<unknown>
ins\tAPPRART.Acc.Sg.Neut\tin
Ausland\tN.Reg.Acc.Sg.Neut\tAusland
weitergeleitet\tVPP.Full.Psp\tweitergeleiten|weiterleiten
.\tSYM.Pun.Sent\t."""

# Teilen Sie das Ausgangskorpus an Zeilenumbrüchen in
# einzelne Zeilen auf.

# Schauen Sie sich nacheinander jede Zeile an

    # Falls die Zeile leer ist, geben Sie einen Zeilenumbruch aus

    # Falls die Zeile nicht leer ist
        # Teilen Sie jede Zeile an den Tab-Stops in Token, Tag und Lemma auf

        # Teilen Sie das Tag am Punkt in einzelne Bestandteile auf
        
        # Fügen Sie den ersten Teil des Tags mit einem Schrägstrich
        # an das Token an
        
        # Geben Sie die Kombination Token/Tag und evtl. noch
        # ein Leerzeichen aus
Die Endausgabe im Ecplipse muss also wie folgt aussehen:

Code: Alles auswählen

Rund/ADJD 40/CARD Prozent/N aller/PRO staatlichen/ADJA Gelder/N für/APPR Verkehr/N ,/SYM Gesundheit/N und/CONJ Soziales/N würden/VFIN unterschlagen/VPP ./SYM 

Die/ART dadurch/PROADV verursachten/ADJA Schäden/N beliefen/VFIN sich/PRO auf/APPR rund/ADJD 20/CARD Milliarden/N Dollar/N im/APPRART Jahr/N ./SYM 

Ein/ART Teil/N der/ART unterschlagenen/ADJA Gelder/N werde/VFIN von/APPR der/ART Verwaltungsmafia/N ins/APPRART Ausland/N weitergeleitet/VPP ./SYM 
Mein Programm hab ich nun so geschrieben:

Code: Alles auswählen

# Teilen Sie das Ausgangskorpus an Zeilenumbrüchen in
# einzelne Zeilen auf.
#korpus_str = str(korpus)
#korpus_liste = list(korpus_str.splitlines())
korpus_liste = korpus.splitlines()

# Schauen Sie sich nacheinander jede Zeile an
for zeile in korpus_liste:
    zeilenlaenge = len(zeile)
    #print zeile
    #print zeilenlaenge
    
    # Falls die Zeile leer ist, geben Sie einen Zeilenumbruch aus
    if zeilenlaenge == 0:
        print
    # Falls die Zeile nicht leer ist
    else:
        # Teilen Sie jede Zeile an den Tab-Stops in Token, Tag und Lemma auf
        liste_einzelner_zeilen = zeile.split("\t")
        #print liste_einzelner_zeilen
        #print liste_einzelner_zeilen[1]
        
        # Teilen Sie das Tag am Punkt in einzelne Bestandteile auf
        tag_replaced = liste_einzelner_zeilen[1].replace(".", " ")
        tag_liste = tag_replaced.split()        
        
        # Fügen Sie den ersten Teil des Tags mit einem Schrägstrich
        # an das Token an
        token = liste_einzelner_zeilen.pop(0)
        tag = tag_liste.pop(0)
        tokentag = ''.join(token) + "/" +''.join(tag)
        fertige_kombination = ''.join(tokentag)
        test1 = fertige_kombination.split()
        
        # Geben Sie die Kombination Token/Tag und evtl. noch
        # ein Leerzeichen aus
        print test1
Die Ausgabe bei mir ist

Code: Alles auswählen

[u'Rund/ADJD']
[u'40/CARD']
[u'Prozent/N']
[u'aller/PRO']
[u'staatlichen/ADJA']
[u'Gelder/N']
[u'f\xfcr/APPR']
[u'Verkehr/N']
[u',/SYM']
[u'Gesundheit/N']
[u'und/CONJ']
[u'Soziales/N']
[u'w\xfcrden/VFIN']
[u'unterschlagen/VPP']
[u'./SYM']

etc.
pp.
Soweit, so gut.

Ich bekomme es aber nicht hin die Listen zusammenzufügen, damit es wie oben in der Endausgabe aussieht.

Kann mir jemand helfen bitte? Ich hab nen Denkfehler im Code irgendwie... :(

Danke sehr schonmal!
Zuletzt geändert von CiveX am Samstag 23. Mai 2009, 12:51, insgesamt 3-mal geändert.
Benutzeravatar
numerix
User
Beiträge: 2696
Registriert: Montag 11. Juni 2007, 15:09

In Zeile 29 das angehängte Leerzeichen entfernen.
In Zeile 33 ein Komma hintendran.

Ansonsten:
Überall, wo list() steht, kannst du das weglassen.
Du brauchst die Länge nicht zu bestimmen, um zu prüfen, ob die Zeichenkette leer ist.
Anstelle von elif ist else ausreichend.
CiveX
User
Beiträge: 34
Registriert: Samstag 23. Mai 2009, 11:48

Verstehe ich jetzt nicht mit Zeile 29 und 33.

Also die Ausgabe von Zeile 29 sieht so aus, also "print token":

Code: Alles auswählen

Rund
40
Prozent
aller
staatlichen
Gelder
für
Verkehr
,
Gesundheit
und
Soziales
würden
unterschlagen
.
Da sind keine Leerzeichen bei

Zeile 33 ist nur ein Test, um zu sehen ob tokentag richtig gejoint wurde in fertige_kombination:

Code: Alles auswählen

[u'Rund/ADJD']
[u'40/CARD']
[u'Prozent/N']
[u'aller/PRO']
[u'staatlichen/ADJA']
[u'Gelder/N']
[u'f\xfcr/APPR']
[u'Verkehr/N']
[u',/SYM']
[u'Gesundheit/N']
[u'und/CONJ']
[u'Soziales/N']
[u'w\xfcrden/VFIN']
[u'unterschlagen/VPP']
[u'./SYM']

[u'Die/ART']
[u'dadurch/PROADV']
[u'verursachten/ADJA']
[u'Sch\xe4den/N']
[u'beliefen/VFIN']
[u'sich/PRO']
[u'auf/APPR']
[u'rund/ADJD']
[u'20/CARD']
[u'Milliarden/N']
[u'Dollar/N']
[u'im/APPRART']
[u'Jahr/N']
[u'./SYM']

[u'Ein/ART']
[u'Teil/N']
[u'der/ART']
[u'unterschlagenen/ADJA']
[u'Gelder/N']
[u'werde/VFIN']
[u'von/APPR']
[u'der/ART']
[u'Verwaltungsmafia/N']
[u'ins/APPRART']
[u'Ausland/N']
[u'weitergeleitet/VPP']
[u'./SYM']
Was ich jetzt will, ist aus diesen Listen dies zu machen:

Code: Alles auswählen

Rund/ADJD 40/CARD Prozent/N aller/PRO staatlichen/ADJA Gelder/N für/APPR Verkehr/N ,/SYM Gesundheit/N und/CONJ Soziales/N würden/VFIN unterschlagen/VPP ./SYM

Die/ART dadurch/PROADV verursachten/ADJA Schäden/N beliefen/VFIN sich/PRO auf/APPR rund/ADJD 20/CARD Milliarden/N Dollar/N im/APPRART Jahr/N ./SYM

Ein/ART Teil/N der/ART unterschlagenen/ADJA Gelder/N werde/VFIN von/APPR der/ART Verwaltungsmafia/N ins/APPRART Ausland/N weitergeleitet/VPP ./SYM 
Benutzeravatar
numerix
User
Beiträge: 2696
Registriert: Montag 11. Juni 2007, 15:09

Meine Angabe beziehen sich auf den Code, der da mal stand.
Den hast du zwischenzeitlich geändert. Jetzt steht da etwas anderes. Dein Problem ...
CiveX
User
Beiträge: 34
Registriert: Samstag 23. Mai 2009, 11:48

Ahjo, ich wollte net mit jedem Beitrag den Code rumkopieren. Mein Fehler. Naja, 1. Beitrag geändert und Problem besteht weiterhin :).

Danke dennoch, vielleicht hilft jemand anders.
Benutzeravatar
numerix
User
Beiträge: 2696
Registriert: Montag 11. Juni 2007, 15:09

Du wolltest die Ausgabe doch so haben, wie die Vorgabe es vorsieht - in vollständigen Sätzen.

Wenn du machst, was ich gepostet habe, hast du das erreicht:

Code: Alles auswählen

korpus_liste = korpus.splitlines()
for zeile in korpus_liste:
    if zeile:
        liste_einzelner_zeilen = zeile.split("\t")
        tag_replaced = liste_einzelner_zeilen[1].replace(".", " ")
        tag_liste = tag_replaced.split()
        token = liste_einzelner_zeilen.pop(0)
        tag = tag_liste.pop(0)
        tokentag = ''.join(token) + "/" +''.join(tag)
        print tokentag,
    else:
        print
Allerdings hast du bei deinem ersten Code eine Zeichenkette ausgegeben, jetzt eine Liste. Das wird dann nie ein ganzer Satz.
CiveX
User
Beiträge: 34
Registriert: Samstag 23. Mai 2009, 11:48

Ah, jetzt verstehe ich es.

Allerdings ist die Leerzeile notwendig.

Die Ausgabe soll ja wie du es gemacht hast sein.

1. Satz
Leerzeile
2. Satz
Leerzeile
3. Satz

Ah, bingo. Gelöst:

Code: Alles auswählen

for line in korpus_list:
    linelenght = len(line)
    
    # Falls die Zeile leer ist, geben Sie einen Zeilenumbruch aus
    if linelenght == 0:
        print "\n"
    # Falls die Zeile nicht leer ist
    else:
        # Teilen Sie jede Zeile an den Tab-Stops in Token, Tag und Lemma auf
        list_single_line = line.split("\t")
        
        # Teilen Sie das Tag am Punkt in einzelne Bestandteile auf
        tag_replaced = list_single_line[1].replace(".", " ")
        tag_liste = tag_replaced.split()        
        
        # Fügen Sie den ersten Teil des Tags mit einem Schrägstrich
        # an das Token an
        token = list_single_line.pop(0)
        tag = tag_liste.pop(0)
        tokentag = ''.join(token) + "/" +''.join(tag)
        finished_combi = ''.join(tokentag)
        test = finished_combi.split()
 
        # Geben Sie die Kombination Token/Tag und evtl. noch
        # ein Leerzeichen aus
        print tokentag,
Jetzt müsste mir nur noch erklären, warum die komma am tokentag am ende das ganze Bewirkt. :)

Die Leerzeile hab ich mit

Code: Alles auswählen

if linelenght == 0:
        print "\n"
gelöst.
Benutzeravatar
numerix
User
Beiträge: 2696
Registriert: Montag 11. Juni 2007, 15:09

CiveX hat geschrieben:Jetzt müsste mir nur noch erklären, warum die komma am tokentag am ende das ganze Bewirkt. :)
Weil print einen Zeilenumbruch bewirkt und ein angehängtes Komma das verhindert ...
Benutzeravatar
Dill
User
Beiträge: 470
Registriert: Mittwoch 10. Januar 2007, 14:52
Wohnort: Köln

was ist das denn für ein tutorial?
in welchem rahmen beschäftigst du dich mit dem thema?

kennst du das NLTK?

http://www.nltk.org/
http://www.kinderpornos.info
BlackJack

@CiveX: Ich glaube Du hast das Ausgabeformat falsch verstanden. Bei einer leeren Zeile in der Eingabe soll ein Zeilenumbruch ausgegeben werden, bei einer nichtleeren Zeile soll das *nicht* passieren! Das ergibt dann *keine* Leerzeilen zwischen den Sätzen, sondern einen Zeilenumbruch am Ende von Sätzen.

Das ist kein Komma am `tokentag`, sondern ein Komma am Ende der ``print``-Anweisung. Und das bewirkt eben genau das. Steht so in der Dokumentation.

Ist übrigens ziemlich "Wortreich" Deine Umsetzung. Das kann man deutlich kompakter schreiben:

Code: Alles auswählen

def main():
    for line in korpus.splitlines():
        if line:
            token, tag, dummy = line.split('\t')
            print '%s/%s' % (token, tag.split('.')[0]),
        else:
            print
Deine ``''.join``\s sind allesamt komplett sinnfrei! Die Bewirken gar nichts, ausser das unnötig Rechenzeit verbraucht wird und das Programm schwerer zu verstehen ist.
CiveX
User
Beiträge: 34
Registriert: Samstag 23. Mai 2009, 11:48

Nichts für ungut, aber wenn ich was hasse ist es Code der so kompakt wie möglich gehalten wird.

Am besten alles in einer Zeile schreibe, so nach dem Motto.
Benutzeravatar
numerix
User
Beiträge: 2696
Registriert: Montag 11. Juni 2007, 15:09

CiveX hat geschrieben:Nichts für ungut, aber wenn ich was hasse ist es Code der so kompakt wie möglich gehalten wird.

Am besten alles in einer Zeile schreibe, so nach dem Motto.
Das trifft den Kern jetzt aber nicht. BlackJack hat nur deutlich gemacht, dass in deinem Code viel überflüssiges ist und das sollte man schon weglassen. Und das, was bei BlackJack herausgekommen ist, ist wahrhaftig nicht so kompakt wie möglich, sondern gut lesbar und nett anzusehen.

Wobei ich finde, dass dein Code für einen Anfänger (?) gar nicht so schlecht aussah, wenn man vom überflüssigen Code absieht. Sehr positiv sind z.B. deine gut verständlichen Bezeichner.

Ich schätze mal, wenn man es drauf anlegt, dann bekommt man das wirklich in eine Zeile (naja, vielleicht nur mit Semikolon?) ...
BlackJack

Nichts für ungut, aber ich mag keinen Code der **unnötig** "geschwätzig" ist. Das heisst nicht, dass ich auf unlesbare Einzeiler stehe, im Gegenteil. Aber ich sehe echt keinen Gewinn darin, hier zum Beispiel das Ergebnis von ``korpus.splitlines()`` an einen Namen zu binden. Das macht das Programm IMHO nicht verständlicher. Im Gegenteil machen viele Namen für jedes kleine Zwischenergebnis ein Programm schwerer zu durchschauen.

Wesentlich unverständlicher wird das Programm aber durch Deine ``pop(0)`` Aufrufe, weil man jetzt plötzlich im Kopf haben muss was diese Listen vor und nach dem Aufruf enthalten haben. Wieso *veränderst* Du die Datenstrukturen da? Letztendlich sind das und Indexzugriffe schwerer zu durchschauen als die einzelnen Komponenten gleich nach dem "splitten" an aussagekräftige Namen zu binden.

Von diesen wirklich total sinnfreien ``''.join()``\s mal ganz abgesehen. Ich musste dreimal hinschauen um wirklich sicher zu sein, dass die an jeder Stelle nutzlos sind und genau das liefern was man reinsteckt.

IMHO ist mein Quelltext nicht *unverständlich* kurz. Einzig das ``tag.split('.')[0]`` würde ich vielleicht in eine eigene Funktion auslagern, aber der Rest ist normales Python für "production code" und nicht für einen "obfuscation contest".
CiveX
User
Beiträge: 34
Registriert: Samstag 23. Mai 2009, 11:48

Ich Anfänger? Ja!

Warum ich pop() nehme, weil z.B.:

Code: Alles auswählen

Schäden\tN.Reg.Nom.Pl.Masc\tSchaden
beliefen\tVFIN.Full.3.Pl.Past.Ind\tbelaufen 
Ich will

Code: Alles auswählen

Schäden/N
beliefen/VFIN
haben und nicht

Code: Alles auswählen

Schäden/Nom
beliefen/Pl
jeweils das 1. vor dem 1. Punkt wird dann an das Wort mit einem / angehängt.

Ich wüsste halt nicht wie ich es anders lösen sollte.

Deshalb ging ich von der Idee aus, dass

1) Korpus in Zeilen spliten, also mit splitlines()
2) Jede Zeile in eine Liste umwandeln, nach jedem Tabstop
dann hab ich dann ['Token', 'Tag', 'Lemma'] also z.B. ['Schäden','N.Reg.Nom.Pl.Masc','Schaden'].

ja und dann wüsste ich nicht wirklich weiter und hab überlegt wie ich nun aus der Liste, aus dem 2. Element das N vor dem ersten . rausnehme und in das 1. Element in die Liste mit einem / einfüge.

Also bin ich dann auf die Idee gekommen das 2. Element aus der Liste einzel zu betrachten. Das war dann in tag_list der Fall.

So nun hatte ich 2 Listen. einmal list_single_lines und einmal tag_list.

Ich könnte somit bei den Listen jeweils auf das 1. Element zugreifen und bekam somit das Token und den Tag.

Irgendwie müsste ich ja nun das einzelne Element Token und Tag zusammenfügen. Ich kannte soweit nur die .join Methode, also habe ich diese angewendet.

Nun hab ich dann, nach der Aufgabe, Token+Schrägstrich+Tag drausgemacht.

Und dannach müsste ich das ganze als jeweils einzigen Satz ausgeben.

So war zumindest mein Gedankengang. Liege ich falsch?
Benutzeravatar
numerix
User
Beiträge: 2696
Registriert: Montag 11. Juni 2007, 15:09

numerix hat geschrieben:Ich schätze mal, wenn man es drauf anlegt, dann bekommt man das wirklich in eine Zeile (naja, vielleicht nur mit Semikolon?) ...
Geht auch ohne Semikolon! :D

Code: Alles auswählen

print"".join('%s/%s '%(l.split('\t')[0],l.split('\t')[1].split('.')[0])if l else"\n"for l in korpus.split("\n"))
BlackJack

@Civex: ``liste.pop(index)`` *entfernt* das angegebene Element aus der Liste, das heisst die Liste wird verändert; alle nachfolgenden Elemente werden eins nach vorne gerückt. Warum machst Du das, statt einfach nur auf das erste Element zuzugreifen ohne die Liste zu verändern. Dass Du grundsätzlich weisst wie das geht zeigt Dein Quelltext ja auch: mit ``liste[index]`.

Andererseits sind solche Indexe immer ein bisschen unschön, weil man da "magische" Zahlen verwendet. Der Name `tag` für ein Tag ist jedenfalls verständlicher als eine 1. Deshalb habe ich im ersten Verarbeitungsschritt der Zeile die drei Bestandteile direkt an Namen gebunden:

Code: Alles auswählen

    token, tag, dummy = line.split('\t')
Und `token` und `tag` sind IMHO im weiteren Programmverlauf verständlicher als `list_single_line[0]` und `list_single_line[1]` bzw. `list_single_line.pop(0)`. Wobei nach Letzterem `list_single_line[1]` plötzlich eine andere Bedeutung bekommt. Ab da ist das nämlich nicht mehr das Tag sondern das Lemma.

Statt `dummy` hätte ich auch den Namen `lemma` nehmen können, aber ich kennzeichne auf diese Weise gerne Namen, die nicht verwendet werden.

Als unleserlicher Einzeiler sähe das übrigens so aus:

Code: Alles auswählen

print''.join((lambda a,b,_:a+'/'+b.split('.')[0]+' ')(*s.split('\t'))if s else'\n'for s in korpus.splitlines())
:-)

Edit: @numerix: Ätsch, meins ist ein Zeichen kürzer. :-P
Benutzeravatar
numerix
User
Beiträge: 2696
Registriert: Montag 11. Juni 2007, 15:09

BlackJack hat geschrieben:Edit: @numerix: Ätsch, meins ist ein Zeichen kürzer. :-P
Hab ich extra lang gemacht - ich wollte dich doch auch mal gewinnen lassen ... :wink:
CiveX
User
Beiträge: 34
Registriert: Samstag 23. Mai 2009, 11:48

Hast ja recht, ich hab es soweit vereinfacht, wie es für mich zumindest nachvollziehbar und verständlich ist:

Code: Alles auswählen

# Für jede Zeile im Korpus
for line in korpus.splitlines():
    linelenght = len(line) #Zeilenlänge je Zeile ermitteln
    
    # Ist die Zeilenlänge = 0, also leer, dann Zeilenumbruch
    if linelenght == 0:
        print 
    
    # Ist sie nicht leer, dann
    else:
        # Jede Zeile wird aufgeteilt an den Tabstobs und an Variablen Token, Tag und Lemma übergeben
        token, tag, lemma = line.split('\t')

        # Das 1. Tag vor dem 1. Punkt wird an an neue Variable übergeben
        tag_neu = tag.split(".")[0]    

        # Zusammenfügen von Token + Schrägstrich +  Tag
        tokentag = token + "/" + tag_new

        # finale Ausgabe in geforderter Form
        print tokentag,
Ist doch nun viel besser. Danke euch allen :)!

Was ich allerdings nicht verstehe ist, warum man auch:

Code: Alles auswählen

for line in korpus.splitlines():
	if line:
		blablub
	
	else:
		print
Schreiben kann und es genauso geht wie mit dem Ermitteln der Zeilenlänge. Ich mein wo frage ich denn da ob Zeile leer ist oder net? "if line:" sagt mir überhaupt nix.
Zuletzt geändert von CiveX am Samstag 23. Mai 2009, 19:00, insgesamt 2-mal geändert.
BlackJack

@numerix: Na dann: 6 Zeichen kürzer als Deins:

Code: Alles auswählen

print''.join((lambda a,b,_:a+'/'+b.split('.')[0]+' ')(*s.split())if s else'\n'for s in korpus.split('\n'))
Benutzeravatar
Dill
User
Beiträge: 470
Registriert: Mittwoch 10. Januar 2007, 14:52
Wohnort: Köln

civex, ein leerer string ist false, alle anderen true.
http://www.kinderpornos.info
Antworten