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
A maneira como isso funciona é bastante simples, mas a ordem dos comandos é significativa. Começamos gravando o que é a primeira linha e imprimindo. Vamos para a linha seguinte e verificamos se a próxima linha contém texto anterior. Se isso acontecer - não fazemos nada. Se isso não acontecer, esse é um novo caminho diferente.
A abordagem original foi falha e falhou quando havia caminhos adjacentes com a mesma subseqüência principal, como /var/zomg
e /var/zomgkthx
(Obrigado ao Chai T.Rex por apontar isso). O truque é acrescentar "/" ao caminho antigo para significar o final dele, quebrando assim a substring. A mesma abordagem é usada na alternativa em Python abaixo.
Alternativa em Python
#!/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,'')
Execução da amostra:
$ ./reduce_paths.py paths.txt
/proc
/run
/tmp
/home/bytecommander/ramdisk
/var/zomg
/var/zomgkthx
/zomg
/zomgkthx
Essa abordagem é semelhante ao awk-one. Idéia é a mesma coisa: registre a primeira linha e continue imprimindo e redefinindo a variável de rastreamento somente quando encontrarmos uma linha que não tenha uma variável de rastreamento como substring inicial.
Alternativamente, uma vez pode usar a função os.path.commonprefix()
também.
#!/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,'')