merkwürdigen String in Mac umwandeln

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
herates
User
Beiträge: 8
Registriert: Mittwoch 17. November 2010, 16:54

Hallo Jungs und Mädels,

ich habe hier ein minderschweres Problem, bei dem ich aber verzweifle. Denkblockade???

Ich habe einen String

Code: Alles auswählen

\x1c\xdf\x0ff\x8f\xce
die ersten zwei Zeichen hinter einem \x sind eine Hexadezimal Zahl. Wenn ich das also splitte erhalte ich:

Code: Alles auswählen

['1c', 'df', '0ff', '8f', 'ce']
Jetzt kann ich die items langlaufen und bei items die > 2 sind einfach die angehängten zeichen mittels hex() in eine Hexadezimalzahl umwandeln und schon habe ich meine Macadresse.

Jetzt das Problem. Es kann sein, das Steuercodes in dem String vorkommen. Beispielsweise:

Code: Alles auswählen

\x1c\xdf\x0f\x94\n\xe4
Gesplittet:

Code: Alles auswählen

['1c', 'df', '0f', '94\\n', '\e4']
Man beachte das zusätzliche '\'. Wenn ich jetzt die Items einzeln überprüfe kann ich natürlich immer ein \+Zeichen zusammen betrachten und umwandeln, aber:

Code: Alles auswählen

\x1c\xdf\x0f\xb5,\\
Gesplittet:

Code: Alles auswählen

['1c', 'df', '0f', 'b5,\\\\']
wer sagt mir, dass das '\' ein Steuerzeichen ist und kein einfaches Ascii-Zeichen? Hier sind die \\\\ natürlich einfach nur ein \ mit einem zusätzlichen \ zur markierung, dass es kein steuerzeichen ist.
Zum Beispiel:

Code: Alles auswählen

['1c', 'df', '0f', 'b5,\n\\\']
Nun könnte das ja entweder \ + n seind oder \n als Steuerzeichen für Newline.

Hat jemand die Idee, wie ich das schön angehen kann?

Grüße
Wolfgang
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Hallo und willkommen im Forum!

Du machst die das ganze wahrscheinlich ein wenig umständlich. Der String, welchen du als erstes agibst, ist nur die Repräsentation eines Strings. "\x1c" sind keine viert Bytes sondern nur ein einziges. Du kannst also wie gewohnt über Indizes darauf zugreifen:

Code: Alles auswählen

>>> spam = "\x1c\xdf\x0ff\x8f\xce"
>>> for char in spam:
...     print repr(char), ord(char), hex(ord(char))
... 
'\x1c' 28 0x1c
'\xdf' 223 0xdf
'\x0f' 15 0xf
'f' 102 0x66
'\x8f' 143 0x8f
'\xce' 206 0xce
Sebastian
Zuletzt geändert von EyDu am Mittwoch 17. November 2010, 17:43, insgesamt 1-mal geändert.
Das Leben ist wie ein Tennisball.
Benutzeravatar
b.esser-wisser
User
Beiträge: 272
Registriert: Freitag 20. Februar 2009, 14:21
Wohnort: Bundeshauptstadt B.

Was hast du denn vor ?
Das struct-modul könnte noch helfen:

Code: Alles auswählen

In[1]: import struct

In [2]: struct.unpack("6B", "\x1c\xdf\x0ff\x8f\xce")
Out[2]: (28, 223, 15, 102, 143, 206)
hth, Jörg
herates
User
Beiträge: 8
Registriert: Mittwoch 17. November 2010, 16:54

Hallo Sebastian,

danke erstmal für die hilfe und das willkommen..


aber deine idee klappt so nicht:

Code: Alles auswählen

\x1c\xdf\x0ft\xe1+
'\\' 92 0x5c
'x' 120 0x78
'1' 49 0x31
'c' 99 0x63
'\\' 92 0x5c
'x' 120 0x78
'd' 100 0x64
'f' 102 0x66
'\\' 92 0x5c
'x' 120 0x78
'0' 48 0x30
'f' 102 0x66
't' 116 0x74
'\\' 92 0x5c
'x' 120 0x78
'e' 101 0x65
'1' 49 0x31
'+' 43 0x2b
wie hier deutlich wird. das problem ist, dass ich hier wirklich einen string habe, der aus hexadezimal zahlen besteht (markiert durch das \x) und aus dezimalzahlen.
siehe das beispiel oben. die letzten 5 zeichen sind \xe1+. das \x sagt mir, dass die folgenden 2 zeichen hexadezimal sind. das folgende + ist jedoch ein dezimalzeichen, das umgerechnet 2b hexadezimal ist.
herates
User
Beiträge: 8
Registriert: Mittwoch 17. November 2010, 16:54

hallo jörg,

ich habs mal probiert. sah auch gut aus. wenn ich das über mehrer datensätze laufen lassen will bekomme ich jedoch die meldung:

Code: Alles auswählen

struct.error: unpack str size does not match format
ich verstehe struct jetzt nicht so schnell, als das ich den fehler auf die schnelle nachvollziehen könnte.

was ich will ist einfach. der string repräsentiert einfach eine macadresse. diese will ich in das format xx:xx:xx:xx:xx:xx formatieren.
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Woher bekommst du denn einen String in dieser Form? Am einfachsten wäre es, wenn man dort ansetzt. Wenn du die Möglichkeit nicht hast, dann tut es auch ein einfacher regulärer Ausdruck.
Das Leben ist wie ein Tennisball.
herates
User
Beiträge: 8
Registriert: Mittwoch 17. November 2010, 16:54

fänd ich toll wenn das ginge. so einen mist bekommt man über eine snmp abfrage auf cisco switchen.
BlackJack

@herates: Wo bekommst Du diese Zeichenketten denn her? Und in welchem Kontext sehen die so aus? Vielleicht ist es besser wenn Du das mal in der Python-Shell ausprobierst und hier 1:1 reinkopierst, sonst weiss man nie sicher ob es jeweils um eine Zeichenkette geht, die tatsächlich so etwas wie Backslash, 'x', '1', 'c' enthält, oder um die `repr()` einer Zeichenkette mit nur einem Zeichen das halt nicht "druckbar" ist. Ist Dir der Unterschied klar!?

Code: Alles auswählen

In [40]: a = '\x1c'

In [41]: print a


In [42]: len(a)
Out[42]: 1

In [43]: b = '\\x1c'

In [44]: print b
\x1c

In [45]: len(b)
Out[45]: 4
Falls es wirklich um Fall `b` geht, dann hör bitte sofort auf solche Daten zu produzieren. Das kann man zwar mit der `decode()`-Methode auf Zeichenketten und der 'string-escape'-Kodierung wieder rückgängig machen, aber das ist ein ziemlich blödes Datenformat. Da sollte man besser die Funktionen aus dem `binascii`-Modul verwenden.
herates
User
Beiträge: 8
Registriert: Mittwoch 17. November 2010, 16:54

zweiteres.
dann fangen wir mal ganz vorne an. mittels dem moduls pysnmp erhalte ich eine liste:

Code: Alles auswählen

varBindTable = cmdgen.CommandGenerator().nextCmd(snmpConnection, udpConnection, oid)
type(varbindTable)
<type 'list'>
in der form

Code: Alles auswählen

print varbindTable
[[(ObjectName('1.3.6.1.4.1.9.9.513.1.1.1.1.2.0.15.247.72.161.96'), OctetString('\x00\re[v\x1d'))], [(ObjectName('1.3.6.1.4.1.9.9.513.1.1.1.1.2.0.15.247.72.163.16'), OctetString('\x00\re[v\x85'))], [(ObjectName('1.3.6.1.4.1.9.9.513.1.1.1.1.2.0.15.247.122.99.192'), OctetString('\x00\x0f\x90>:S'))], [(ObjectName('1.3.6.1.4.1.9.9.513.1.1.1.1.2.0.17.92.104.31.240'), OctetString('\x00\re[v\x1a'))], [(ObjectName('1.3.6.1.4.1.9.9.513.1.1.1.1.2.0.20.27.88.117.176'), OctetString('\x00\x14\x1c\xed/\xbc'))], [(ObjectName('1.3.6.1.4.1.9.9.513.1.1.1.1.2.0.23.223.167.243.144'), OctetString('\x00\x1b\xd5\x130\xb6'))], [(ObjectName('1.3.6.1.4.1.9.9.513.1.1.1.1.2.0.23.223.168.26.80'), OctetString('\x00\x1b\xd5\x13>\x18'))], [(ObjectName('1.3.6.1.4.1.9.9.513.1.1.1.1.2.0.25.169.253.113.240'), OctetString('\x00\x1a/\x83Tt'))],..............
wobei jedes Element aus der Liste wieder vom Typ list ist mit der Länge 1.
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Dann solltest du dir mal die Attribute und Methoden der Objekte anschauen. Dort kommst du sicher an die echten Daten.
Das Leben ist wie ein Tennisball.
BlackJack

@herates: Damit ist jetzt aber immer noch nicht klar wie Du an eine Zeichenkette in der am Anfang gezeigten Form kommst? Ich meine Du arbeitest dann doch hoffentlich nicht mit der *Zeichenkettenrepräsentation* von so einer Datenstruktur sondern mit den Objekten selber!?
herates
User
Beiträge: 8
Registriert: Mittwoch 17. November 2010, 16:54

sorry, Hinweis vergessen.
str() auf das Listenobjekt und mit split() und strip() die benötigte Zeichenkette extrahiert.

Und für das Modul selber habe ich keine gescheiten Methoden gefunden. In einem Beispiel machen die es so:

Code: Alles auswählen

                for varBindRow in varBindTable:
                        for oid, val in varBindRow:
                                if val is None:
                                        print oid.prettyPrint()
                                else:
                                        print '%s = %s' % (oid.prettyPrint(), val.prettyPrint())
dabei kommt sowas dann raus:

Code: Alles auswählen

1.3.6.1.4.1.9.9.513.1.1.1.1.2.0.34.85.117.52.16 = "U2À
1.3.6.1.4.1.9.9.513.1.1.1.1.2.0.34.85.117.52.96 = "U4à
....
was genau prettyPrint() macht, konnte ich auf die schnelle nicht herausfinden.
BlackJack

@herates: Das ist Python und kein Bash-Skript, also benutze doch bitte die Objekte und nicht solche hässlichen Hacks. :roll:
herates
User
Beiträge: 8
Registriert: Mittwoch 17. November 2010, 16:54

wie sag ich immer. kack nich rum, brings mir bei....

das schimpft sich moderator....

ich bin nicht der spezi in python (wie auch nach 2 wochen). also pysnmp verwendet.. was bekomm ich? eine liste von listenobjekten mit der länge 1.
was soll ich den jetzt damit großartig anfangen?

gibt mir tips, literatur oder sonstwas, aber auf ein Augenverdrehen kann ich verzichten.
lunar

@herates: Mag sein, dass Du auf Augendreher verzichten kannst, aber dieses Forum kann vor allem auch gut auf Dich verzichten. Denke daran, wenn Du das nächste Mal ein verdientes Mitglied, welches noch dazu Moderator ist, derart anzufallen beabsichtigst.

Es ist im Übrigen nicht Aufgabe dieses Forums, Dir die absoluten Grundlagen der Sprache Python beizubringen, sondern Dir bei konkreten Fragen zu helfen. Da Dir diese Grundlagen ganz offensichtlich fehlen, kann man Dir nicht sinnvoll helfen. Lies bitte erst einmal das Tutorial, und lerne, mit Listen und Objekten umzugehen.
BlackJack

@herates: Mal davon abgesehen, dass ich Dir für die Murkslösung auch schon einen Hinweis gegeben habe, könntest Du auch einfach mal ein bisschen herumprobieren. Was solche `OctetString`-Objekte für Methoden haben -- da wird in dem Beispielschnippsel ja auch schon was interessantes gezeigt -- oder wie die auf die grundlegenden Umwandlungsfunktionen reagieren. Wenn man eine Zeichenkette haben möchte, bietet sich ja zum Beispiel `str()` an. Und siehe da:

Code: Alles auswählen

In [79]: a
Out[79]: OctetString('\x00\re[v\x1d')

In [80]: str(a)
Out[80]: '\x00\re[v\x1d'
Vielleicht geht ja auch Indexzugriff, dann sind die Dinger auch "iterable":

Code: Alles auswählen

In [81]: a[0]
Out[81]: '\x00'

In [82]: map(ord, a)
Out[82]: [0, 13, 101, 91, 118, 29]
Juhuu.
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

herates hat geschrieben:ich bin nicht der spezi in python (wie auch nach 2 wochen). also pysnmp verwendet.. was bekomm ich? eine liste von listenobjekten mit der länge 1.
was soll ich den jetzt damit großartig anfangen?
Also reine Logik würde mir raten, mal das erste Objekt aus dieser Liste rauszuholen und anzuschauen. Vielleicht hat es ja interessante Attribute?

Aber eigentlich hab ich jetzt auch nicht viel Lust da weiter zu schreiben, weil ich mich auch Moderator schimpfe und diese bei dir offenbar unbeliebt sind.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
herates
User
Beiträge: 8
Registriert: Mittwoch 17. November 2010, 16:54

"Thomas, dass ist Deutsch und kein Französisch, also benutz doch die Deutsch-Grammatik und nicht solch komische Konstrukte :roll: "
Du bist der Schüler. Hast du noch Lust weiter zu lernen? Fühlst du dich nicht vor der ganzen Klasse angegriffen?
Lies bitte erst einmal das Tutorial, und lerne, mit Listen und Objekten umzugehen.
Genau das hätte er schreiben können.
weil ich mich auch Moderator schimpfe und diese bei dir offenbar unbeliebt sind.
wie ich verallgemeinerungen hasse

Um wieder sachlich zu werden:

Code: Alles auswählen

Python 2.4.3 (#1, Sep  8 2010, 11:38:44)
[GCC 4.1.2 20080704 (Red Hat 4.1.2-48)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> from pysnmp.entity.rfc3413.oneliner import cmdgen
>>> oid = (1, 3, 6, 1, 4, 1, 9, 9, 513, 1, 1, 1, 1, 2)
>>> ip="123.123.123.123"
>>> port=161
>>> community="dfsrtfwe"
>>> udpConnection =  cmdgen.UdpTransportTarget((ip, port))
>>> snmpConnection = cmdgen.CommunityData('test-agent', community)
>>> varBindTable = cmdgen.CommandGenerator().nextCmd(snmpConnection, udpConnection, oid)
>>> type(varBindTable)
<type 'tuple'>
>>>>>> len(varBindTable)
4
# okay hier habe ich mich geirrt. varBindTable ist also ein Tupel. Die ersten 3 Elemente sind StatusCodes von der Abfrage. Das vierte:
>>> print varBindTable[3]
[[(ObjectName('1.3.6.1.4.1.9.9.513.1.1.1.1.2.0.15.247.72.161.96'), OctetString('\x00\re[v\x1d'))], [(ObjectName('1.3.6.1.4.1.9.9.513.1.1.1.1.2.0.15.247.72.163.16'), OctetString('\x00\re[v\x85'))], [(ObjectName('1.3.6.1.4.1.9.9.513.1.1.1.1.2.0.15.247.122.99.192'), OctetString('\x00\x0f\x90>:S'))], [(ObjectName('1.3.6.1.4.1.9.9.513.1.1.1.1.2.0.17.92.104.31.240'), OctetString('\x00\re[v\x1a'))], [(ObjectName('1.3.6.1.4.1.9.9.513.1.1.1.1.2.0.20.27.88.117.176'), OctetString('\x00\x14\x1c\xed/\xbc'))], [(ObjectName('1.3.6.1.4.1.9.9.513.1.1.1.1.2.0.23.223.167.243.144'), OctetString('\x00\x1b\xd5\x130\xb6'))], [(ObjectName('1.3.6.1.4.1.9.9.513.1.1.1.1.2.0.23.223.168.26.80'), OctetString('\x00\x1b\xd5\x13>\x18'))], [(ObjectName('1.3.6.1.4.1.9.9.513.1.1.1.1.2.0.25.169.253.113.240'), OctetString('\x00\x1a/\x83Tt'))], [(ObjectName('1.3.6.1.4.1.9.9.513.1.1.1.1.2.0.25.169.253.132.64'), OctetString('\x00\x1a/\x83V\xba'))], [(ObjectName('1.3.6.1.4.1.9.9.513.1.1.1.1.2.0.27.212.134.7.96'), OctetString('\x00\x0c\x85\xa8\x89\x88'))], [(ObjectName('1.3.6.1.4.1.9.9.513.1.1.1.1.2.0.28.88.175.138.112'), OctetString('\x00\x0c\x85\xf5\xb6\xe0'))]]
>>> tmp = varBindTable[3]
>>> type(tmp)
<type 'list'>
>>> len(tmp)
11
>>> tmp = tmp[1]   # um mir mal eins rauszugreifen
>>> type(tmp)
<type 'list'>
>>> len(tmp)
1
>>> tmp = tmp[0]
>>> type(tmp)
<type 'tuple'>     # okay ich gebe zu auch hier meine hausaufgaben nicht gemacht zu haben
>>> print tmp
(ObjectName('1.3.6.1.4.1.9.9.513.1.1.1.1.2.0.15.247.72.163.16'), OctetString('\x00\re[v\x85'))
>>> len(tmp)
2
>>> tmp = tmp[1]
>>> type(tmp)
<type 'instance'>
>>> print tmp
e[v
jetzt hänge ich und finde dazu auch nichts.
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Die dir-Funktion wird auch in jedem Tutorial behandelt.
Das Leben ist wie ein Tennisball.
BlackJack

@herates: ``print`` fragt Objekte nach ihrer repräsentation als Zeichenkette, also das was `str()` auch macht. Und genau da wolltest Du doch heran kommen. Es macht natürlich nicht viel Sinn das als Zeichenkette so auszugeben, denn es handelt sich ja um sechs Bytes die als Text gesehen keinen Sinn ergeben. Wie man daraus sechs Zahlen mit den Bytewerten macht, habe ich ja schon gezeigt.
Antworten