AWK
$ awk -F '/' 'oldstr && NR>1{ if($0!~oldstr"/"){print $0;oldstr=$0}};NR == 1{print $0;oldstr=$0}' paths.txt
/proc
/run
/tmp
/home/bytecommander/ramdisk
/var/zomg
/var/zomgkthx
/zomg
/zomgkthx
Die Funktionsweise ist einfach genug, aber die Reihenfolge der Befehle ist wichtig. Wir beginnen damit, die erste Zeile aufzuzeichnen und auszudrucken. Wir gehen zur folgenden Zeile und prüfen, ob die nächste Zeile vorherigen Text enthält. Wenn ja, tun wir nichts. Wenn nicht, ist das ein anderer, neuer Weg.
Der ursprüngliche Ansatz war fehlerhaft und schlug fehl, wenn benachbarte Pfade mit demselben führenden Teilstring wie /var/zomg
und vorhanden waren /var/zomgkthx
(Dank an Chai T.Rex für den Hinweis). Der Trick besteht darin, "/" an den alten Pfad anzuhängen, um dessen Ende zu kennzeichnen, wodurch die Teilzeichenfolge unterbrochen wird. Der gleiche Ansatz wird in der folgenden Python-Alternative verwendet.
Python-Alternative
#!/usr/bin/env python
import sys,os
oldline = None
with open(sys.argv[1]) as f:
for index,line in enumerate(f):
path = line.strip()
if index == 0 or not line.startswith(oldline):
print(path)
oldline = os.path.join(path,'')
Probelauf:
$ ./reduce_paths.py paths.txt
/proc
/run
/tmp
/home/bytecommander/ramdisk
/var/zomg
/var/zomgkthx
/zomg
/zomgkthx
Dieser Ansatz ähnelt awk-one. Die Idee ist dieselbe: Zeichnen Sie die erste Zeile auf und drucken und setzen Sie die Verfolgungsvariable nur dann weiter, wenn wir auf eine Zeile stoßen, die keine Verfolgungsvariable als Startzeichenfolge hat.
Alternativ könnte einmal auch die os.path.commonprefix()
Funktion verwendet werden.
#!/usr/bin/env python
import sys,os
oldline = None
with open(sys.argv[1]) as f:
for index,line in enumerate(f):
path = line.strip()
if index == 0 or os.path.commonprefix([path,oldline]) != oldline:
print(path)
oldline = os.path.join(path,'')
awk
Befehl scheint für/zomg\n/zomgkthx
die zweite Zeile/zomgkthx
fehlzuschlagen , ist kein Unterverzeichnis von/zomg
, aber er wird entfernt.