String auseinander stückeln

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.
Antworten
kromonos
User
Beiträge: 34
Registriert: Freitag 9. Januar 2009, 02:37
Wohnort: Trier
Kontaktdaten:

Gibt es eine möglichkeit, wie ich einen String mit folgendem Inhalt in einem Array ablegen kann:

":Kromonos!Kromonos@user-helfen-usern.de PRIVMSG #test :Dies ist eine Testnachricht"

So, dass der Array wie folgt aussehen würde:

Array = ['Kromonos','kromonos@user-helfen-usern.de','PRIVMSG','#test','Dies ist eine Testnachricht']

Ein einfaches split() würde nicht funktionieren, da dann die komplette nachricht auseinander genommen würde -.-
xmpp:kromonos@user-helfen-usern.de
HomePage/IT-Forum: http://www.user-helfen-usern.de
BlackJack

Dann nimm halt keine einfachen `split()`\s sondern überlege woran man noch splitten kann. Das muss man nicht alles in einem Schritt tun, und die `str.split()`-Methode hat auch noch andere Argumente als die Zeichen an denen die Zeichenkette zerlegt werden soll.

Dazu müsstest Du wissen welche Teile der Zeichenkette fest sind und welche Variabel. An diesem einen Beispiel kann man jetzt keinen Vorschlag machen, der bei jeder Zeichenkette funktioniert.
Dauerbaustelle
User
Beiträge: 996
Registriert: Mittwoch 9. Januar 2008, 13:48

Hallo,
das geht mit `str.split([char])`

Code: Alles auswählen

In [1]: s = ":Kromonos!Kromonos@user-helfen-usern.de PRIVMSG #test :Dies ist eine Testnachricht" 

In [4]: foo, privmsg, test, msg = s.split(' ', 3) # nach Leerzeichen splitten, jedoch höchstens drei mal (weil sonst die Nachricht auch geteilt werden würde)

In [5]: foo, privmsg, test, msg
Out[5]: 
(':Kromonos!Kromonos@user-helfen-usern.de',
 'PRIVMSG',
 '#test',
 ':Dies ist eine Testnachricht')

In [6]: name, mail = foo[1:].split('!')

In [7]: name, mail
Out[7]: ('Kromonos', 'Kromonos@user-helfen-usern.de')

In [8]: msg = msg[1:]

# argh, edit (`foo` statt `test` angegeben):
In [9]: name, mail, privmsg, test, msg
Out[9]: 
('Kromonos',
 'Kromonos@user-helfen-usern.de',
 'PRIVMSG',
 '#test',
 'Dies ist eine Testnachricht')
achso, falls du das nicht kennst:

Code: Alles auswählen

In [10]: blah = "Hallo"

In [11]: blah[1:]
Out[11]: 'allo'
kromonos
User
Beiträge: 34
Registriert: Freitag 9. Januar 2009, 02:37
Wohnort: Trier
Kontaktdaten:

BlackJack hat geschrieben:Dann nimm halt keine einfachen `split()`\s sondern überlege woran man noch splitten kann. Das muss man nicht alles in einem Schritt tun, und die `str.split()`-Methode hat auch noch andere Argumente als die Zeichen an denen die Zeichenkette zerlegt werden soll.

Dazu müsstest Du wissen welche Teile der Zeichenkette fest sind und welche Variabel. An diesem einen Beispiel kann man jetzt keinen Vorschlag machen, der bei jeder Zeichenkette funktioniert.
Es ist ein String aus dem IRC Protokoll. Fest sind die Zeichen :, ! und @

Der Beitrag von Dauerbaustelle hilft mir schon massig weiter. Vielen vielen dank :)
xmpp:kromonos@user-helfen-usern.de
HomePage/IT-Forum: http://www.user-helfen-usern.de
Benutzeravatar
helduel
User
Beiträge: 300
Registriert: Montag 23. Juli 2007, 14:05
Wohnort: Laupheim

Moin,

das ganze wäre auch eine gute Gelegenheit, sich mit Regulären Ausdrücken auseinanderzusetzen.

Gruß,
Manuel
Benutzeravatar
str1442
User
Beiträge: 520
Registriert: Samstag 31. Mai 2008, 21:13

.. oder str.index + String Slicing benutzen Wenn garantiert ist, das ! nur einmal auftaucht, ungetestet:

Code: Alles auswählen

result = [string[:string.index("!")]] + string[string.index("!"):].split(" ")
Dauerbaustelle
User
Beiträge: 996
Registriert: Mittwoch 9. Januar 2008, 13:48

Nö, wenn es zweimal auftaucht (das zweite mal nicht als Abgrenzung, sondern als Nachrichtentext), tut das auch, weil index ja immer die erste Position ausgibt.
DasIch
User
Beiträge: 2718
Registriert: Montag 19. Mai 2008, 04:21
Wohnort: Berlin

Code: Alles auswählen

def parse_irc_message(line):
    """Parses a given irc message to prefix, command, params and trailing."""
    line = line.strip()
    prefix = ''
    if line.startswith(':'):
        prefix, line = line[1:].split(' ', 1)
    trailing = ''
    if ' :' in line:
        line, trailing = line.split(' :', 1)
    params = line.split()
    command = params.pop(0).upper()
    return prefix, command, params, trailing
Benutzeravatar
str1442
User
Beiträge: 520
Registriert: Samstag 31. Mai 2008, 21:13

Ja, aber sollte es mehr als einmal als Abgrenzung auftauchen, wirkt eine Slice Lösung doch arg künstlich ;)

Achja, die richtige Lösung wäre demnach:

Code: Alles auswählen

result = [string[:string.index("!")]] + string[string.index("!") + 1:].split(" ", 3)
OffbyOne. ":" zu entfernen durch Replace wäre dann das letzte.
lunar

Code: Alles auswählen

>>> line = ":Kromonos!Kromonos@user-helfen-usern.de PRIVMSG #test :Dies ist eine Testnachricht"
>>> import re
>>> re.match(':(\w+)!(\w+@[a-zA-Z-.]+)\s+([A-Z]+)\s+([#a-z]+)\s+:(.+)', line).groups()
('Kromonos', 'Kromonos@user-helfen-usern.de', 'PRIVMSG', '#test', 'Dies ist eine Testnachricht')
Benutzeravatar
str1442
User
Beiträge: 520
Registriert: Samstag 31. Mai 2008, 21:13

Es gibt auch noch re.split():

Code: Alles auswählen

>>> re.split(r"[! ]", ":Kromonos!Kromonos@user-helfen-usern.de PRIVMSG #test :Dies ist eine Testnachricht")
[':Kromonos', 'Kromonos@user-helfen-usern.de', 'PRIVMSG', '#test', ':Dies', 'ist', 'eine', 'Testnachricht']
Aber da man {<anzahl an treffern>} nicht angeben kann in den "Character Cases", funktioniert das wohl so nicht. Abgesehen von der Frage, ob es wirklich immer genau 3 Leerzeichen sind.

EDIT:

Code: Alles auswählen

>>> def f(irc_msg):
...  result = re.split(r"[! ]", irc_msg)
...  result[0] = result[0][1:]
...  new_str = " ".join(result[4:])[1:]
...  del result[4:]
...  result.append(new_str)
...  return result
result[4:] = " ".join(result[4:])[1:] hat komischerweise den String komplett vereinzelt :?:

EDIT2:

Achso, ist ja eine Sequenz und wird aufgeteilt... Das hier tuts:

Code: Alles auswählen

>>> def f(irc_msg):
...  result = re.split(r"[! ]", irc_msg)
...  result[0] = result[0][1:]
...  result[4:] = [" ".join(result[4:])[1:]]
...  return result
DasIch
User
Beiträge: 2718
Registriert: Montag 19. Mai 2008, 04:21
Wohnort: Berlin

str1442 hat geschrieben:Abgesehen von der Frage, ob es wirklich immer genau 3 Leerzeichen sind.
Bei PRIVMSGs schon, ansonsten natürlich nicht. Prefix und Trailing sind optional, die Anzahl der Parameter sowieso.
Antworten