IP adressen sortieren

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.
xerxes_

hi,
in einer datei sind ip adresse aufgelistet. die IPs sind nicht geordnet, sprich die IPs liegen kreuz und quer herum. nun ist es meine aufgabe diese zu sortieren. ich hab den inhalt der datei in eine liste gepackt und wollte munter mit list.sort() die sache sortieren lassen. hat auch gut funktioniert nur wisst ihr bestimmt schon wie das resultat aussieht.
192.168.0.0
192.168.0.1
192.168.0.10
192.168.0.11
...

nun meine frage an euch wie würdet ihr dieses problem lösen?
joerg
User
Beiträge: 188
Registriert: Samstag 17. August 2002, 17:48
Wohnort: Berlin
Kontaktdaten:

xerxes_ hat geschrieben: nun meine frage an euch wie würdet ihr dieses problem lösen?

Code: Alles auswählen

ips = ['192.168.0.0', '192.168.0.1', '192.168.0.10', '192.168.0.11']
tmp = [([int(i) for i in ip.split('.')], ip) for ip in ips]
tmp.sort()
ipsorted = [b for a,b in tmp]
Da wird eine Liste gebastelt, deren Elemente Tupel aus den aufbereiteten IPs und den String-IPs sind, dann sortiert, und schließlich wieder die originalen String-IPs rausgesucht.

"Aufbereitung" ist in dem Fall eine Umwandlung des IP-Strings in eine Liste von Zahlen, weil die nämlich besser sortierbar ist.

Alternativ kannst Du zwischenzeitlich auch die Original-Strings vergessen (also aus 'tmp' draußenlassen) und nach dem Sortieren die String-IPs wieder aus den Zahlen zusammenbasteln, das kann übersichtlicher aussehen, aber wird wahrscheinlich nicht schneller sein:

Code: Alles auswählen

tmp = [[int(i) for i in ip.split('.')] for ip in ips]
tmp.sort()
ipsorted = ['%d.%d.%d.%d' % tuple(i) for i in tmp]
Jörg
"Sie sind nicht berechtigt, unrechtmäßige Kopien dieses Datenträgers zu erstellen." - Microsoft-Weisheit auf einer CD von MS-VisualC++-6.0
Gast

Code: Alles auswählen

ips.sort(lambda x,y: cmp(int(x.split(".")[-1]),int(y.split(".")[-1])
@joerg viel zu kompliziert ;)
Gast

Code: Alles auswählen

ips.sort(lambda x,y: cmp(int(x.split(".")[-1]),int(y.split(".")[-1])))
sorry da fehlten klammern
Gast

Bei allen stellen:

Code: Alles auswählen

ips.sort(lambda x,y: cmp([int(i) for i in x.split(".")],[int(i) for i in y.split(".")]))
joerg
User
Beiträge: 188
Registriert: Samstag 17. August 2002, 17:48
Wohnort: Berlin
Kontaktdaten:

Hallo "Gast",
daß man dem sort() eine Vergleichsfunktion schon mitgeben kann, war mir schon bewußt.

Nur ging ich irgendwie davon aus, daß die Liste recht lang ist. Und performancemäßig wird Deine Lösung eher schlecht aussehen. Das wurde IMO auch hier im Forum schon mal diskutiert.

Falls die Geschwindigkeit egal ist, hat so ein Einzeiler natürlich auch einen gewissen Charme. ;-)

Jörg
"Sie sind nicht berechtigt, unrechtmäßige Kopien dieses Datenträgers zu erstellen." - Microsoft-Weisheit auf einer CD von MS-VisualC++-6.0
xerxes_

hi,
eure beispiele funktionieren gut. nun ein weiteres problem:
der inhalt der datei ist folgendermaßen aufgebaut:

192.168.0.21 <aufgelöster hostname> <aufgelöste ipadresse durch hostname>

nun möchte ich gerne die ganze zeile verschieben, jedoch das kriterium bleibt immer die ipadresse. das problem ist, bin nicht so bewandert in der python syntax und im "thinking in python" deshalb suche ich um rat bzw um lösungen.
danke im vorraus
gruß xerxes_
Gast

xerxes_ hat geschrieben: ... das problem ist, bin nicht so bewandert in der python syntax und im "thinking in python" deshalb suche ich um rat bzw um lösungen.
Wenn ein ip.split('.') einen String an den Punkten auftrennt, wie kann man die Zeile dann wohl an Leerzeichen auftrennen, um nur den ersten Teil weiterzuverarbeiten? ;-)

Ersetze mal einen Ausdruck in meinem ersten Vorschlag durch

ip.split(' ')[0].split('.')

Wenn es klappt, war es die richtige Stelle! Wenn nicht, suche weiter! ;-)

Jörg
joerg
User
Beiträge: 188
Registriert: Samstag 17. August 2002, 17:48
Wohnort: Berlin
Kontaktdaten:

Ooops, jetzt isses mir auch passiert, das Einlogenvergessen. Der da oben war von mir!

Jörg
"Sie sind nicht berechtigt, unrechtmäßige Kopien dieses Datenträgers zu erstellen." - Microsoft-Weisheit auf einer CD von MS-VisualC++-6.0
xerxes_

hi,
ich hab vielleicht eine schnelle für mich lösbare lösung erarbeitet :)
und zwar folgendermaßen:

in der datei stehen die ergebnisse einer bestimmten range die aufgelöst wurde zb. 192.168.0.0/19

nun kann ich dem python script die range ja als commandozeilen parameter übergeben -> errechnet die rang -> durchläuft die range -> sucht nach jeder ip in der datei -> findet er was -> nimmt er sich die zeile und schreibt sie einen neue datei... :), schlussendlich kann ich noch einige kosmetische änderung an der datei einfügen zb nach bestimmten bestimmten anzahl von zeilen "seite1" ... "seite2" hinschreiben...
gruß xerxes_
Gast

frage scheint geklärt... aber egal

Code: Alles auswählen

ips.sort(lambda x,y,z={}: cmp(x in z and z[x] or z.__setitem__(x,[int(i) for i in x.split(".")]) or z[x],y in z and z[y] or z.__setitem__(y,[int(i) for i in y.split(".")]) or z[y]))
dies ist schneller ;) aber etz wirds komplizierter ^^
hab grad nen test gemacht deins ist trotzdem schneller um ca 30% als das...
xerxes_

Code: Alles auswählen

import string

source = open("C:\\_dns.log", "r")
dns_list = source.readlines()
source.close()

split_list = []

start1 = 213
start2 = 147
start3 = 0
start4 = 0

ende1 = 213
ende2 = 147
ende3 = 0
ende4 = 255

target = open("C:\\newdns.log", "w")

for j in range(int(start1), int(ende1) + 1):
    for k in range(int(start2), int(ende2) + 1):
        for l in range(int(start3), int(ende3) + 1):
            for h in range(int(start4), int(ende4) + 1):
                
                current_ip = str(j) + "." + str(k) + "." + str(l) + "." + str(h)
                
                for i in dns_list:
                    split_list(string.split(i, " "))
                    
                    try:
                        if(split_list[2] != ''):
                            ip = split_list[2]
                            if(current_ip == ip):
                                target.write(i)
                                break
                                
                        else:
                            ip = split_list[3]
                            if(current_ip == ip):
                                target.write(i)
                                break
                            
                    except:
                        print ''

target.close()

Code: Alles auswählen

>>> 
Traceback (most recent call last):
  File "C:\Python23\Lib\site-packages\Pythonwin\pywin\framework\scriptutils.py", line 310, in RunScript
    exec codeObject in __main__.__dict__
  File "C:\Dokumente und Einstellungen\mz\Desktop\python scripte\sort_advanced.py", line 32, in ?
TypeError: 'list' object is not callable
>>> 
kannste mir helfen jörg?
gruß xerxes_
Dookie
Python-Forum Veteran
Beiträge: 2010
Registriert: Freitag 11. Oktober 2002, 18:00
Wohnort: Salzburg
Kontaktdaten:

Hi xerxes_,

das is wohl etwas daneben:

Code: Alles auswählen

...
split_list(string.split(i, " "))
...
Und 5 verschachtelte Forschleifen ???


Gruß

Dookie
xerxes_

hi
4 verschachtelte schleifen brauch ich um die range hochzuzählen...

die andere um die liste durchzugehen
xerxes_

hier der nächste fehler

Code: Alles auswählen

>>> 
Traceback (most recent call last):
  File "C:\Python23\Lib\site-packages\Pythonwin\pywin\framework\scriptutils.py", line 310, in RunScript
    exec codeObject in __main__.__dict__
  File "C:\Dokumente und Einstellungen\mz\Desktop\python scripte\sort_advanced.py", line 29, in ?
    current_ip = str(j) + "." + str(k) + "." + str(l) + "." + str(h)
TypeError: 'str' object is not callable
>>> 
wie kann ich denn eine integer variable in string umwandeln?
Dookie
Python-Forum Veteran
Beiträge: 2010
Registriert: Freitag 11. Oktober 2002, 18:00
Wohnort: Salzburg
Kontaktdaten:

import string braucht man so gut wie nie!
Statt open sollte file verwendet werden.
xrange ist resourcenschonender als range und auch schneller.

Ich hab mir mal erlaubt, Dein Script etwas aufzuräumen.

Code: Alles auswählen

source = file("C:\\_dns.log", "r")

split_list = []

start1 = 213
start2 = 147
start3 = 0
start4 = 0

ende1 = 213
ende2 = 147
ende3 = 0
ende4 = 255

target = file("C:\\newdns.log", "w")

for j in xrange(int(start1), int(ende1) + 1):
    for k in xrange(int(start2), int(ende2) + 1):
        for l in xrange(int(start3), int(ende3) + 1):
            for h in xrange(int(start4), int(ende4) + 1):
               
                current_ip = "%d.%d.%d.%d" % (j, k, l ,h)
               
                for i in source: # geht auch direkt über die Zeilen einer Datei
                    split_list = i.split(" "))
                   
                    try:
                        if split_list[2] != '':
                            ip = split_list[2]
                            if current_ip == ip:
                                target.write(i)
                                break
                               
                        else:
                            ip = split_list[3]
                            if current_ip == ip:
                                target.write(i)
                                break
                           
                    except: # was willst hier abfangen?
                        print 'oops' # daß zumindest was ausgegeben wird

target.close()
source.close()
Gruß

Dookie
xerxes_

hi dookie,
hab mir den code angeschaut, danke für die überarbeitung. ich hab versucht den code zu interpretieren unter linux mit folgenden versionen
python2 und python2.3 jedoch kommt folgende warnung

Code: Alles auswählen

sys:1: DeprecationWarning: Non-ASCII character '\xfc' in file sort.py on line 24, but no encoding declared; see http://www.python.org/peps/pep-0263.html for details
der code lässt sich auszuführen, nur beträgt das ergebnis eine zeile :).
was bedeutet das und was kann ich dagegen tun?
ich hab mir die page angeschaut jedoch weis ich nichts damit anzufangen
gruß xerxes_
xerxes_

sorry hab mich vertan, das ergebnis ist korrekt würde mich aber dennoch interessieren was diese warnung soll.
ich las irgendwas mit einem zeichensatz. man sollte einen globalen zeichensatz benutzen damit auch andere programmiern besonders aus anderen ländern gleichberechtigt sind beim lesen des codes...
gruß xerxes
Dookie
Python-Forum Veteran
Beiträge: 2010
Registriert: Freitag 11. Oktober 2002, 18:00
Wohnort: Salzburg
Kontaktdaten:

änder mal das ü in ue

Code: Alles auswählen

for i in source: # geht auch direkt ueber die Zeilen einer Datei
ich hab leider keine _dns.log kann das Script leider nicht testen, was heist das Ergebnis beträgt eine Zeile? fehlen Zeilenumbrüche oder wird nur eine Zeile aus source nach target geschrieben?


Gruß

Dookie
xerxes_
User
Beiträge: 1
Registriert: Dienstag 22. Juni 2004, 20:25

so wie gesagt es funktioniert alles so wie es auch soll :) danke für deine hilfe. aber eins wollte ich an diesem programm noch modifizieren. ich möchte gerne commandozeilenparameter verarbeiten. ich denke mal in python gibt es sowas in der art wie argc und argv
gruß xerxes
Antworten