Yo podría hacer esto ciega con respecto a la conversión ruta absoluta (por caminos de depósito forzosamente) mejor?
-
26-09-2019 - |
Pregunta
I necesidad de "a ciegas" (es decir, sin acceso al sistema de ficheros, en este caso el servidor de control de fuente) convertir algunas rutas relativas a rutas absolutas. Así que estoy jugando con dotdots e índices. Para aquellos que tengan curiosidad Tengo un archivo de registro producido por la herramienta de otra persona que a veces salidas de las rutas relativas, y por razones de rendimiento que no quieren acceder al servidor de control de código fuente donde se encuentran los caminos para comprobar si son válidos y más fácilmente convertir a sus equivalentes de ruta absolutos.
He pasado por un número de iteraciones (probablemente tontos) que tratan de conseguir que el trabajo - sobre todo algunas variaciones de iterar sobre el conjunto de carpetas y tratando delete_at (índice) y delete_at (índice-1), pero mi índice guardado incrementando mientras estaba borrando elementos de la matriz de debajo de mí, que no funcionaba para los casos con múltiples dotdots. Cualquier sugerencias sobre cómo mejorar en general o específicamente la falta de apoyo punto punto no consecutiva sería bienvenido.
En la actualidad esto está funcionando con mis ejemplos limitados, pero creo que podría mejorarse. No puede manejar de forma no consecutiva '..' directorios, y probablemente estoy haciendo un montón de cosas despilfarro (y propensos a errores) que probablemente no necesito hacerlo porque soy un poco de un truco.
he encontrado una gran cantidad de ejemplos de conversión de otros tipos de rutas relativas uso de otros idiomas, pero ninguno de ellos parecía encajar mi situación.
Estos son mis caminos ejemplo que necesito para convertir, a partir de:
//depot/foo/../bar/single.c
//depot/foo/docs/../../other/double.c
//depot/foo/usr/bin/../../../else/more/triple.c
a:
//depot/bar/single.c
//depot/other/double.c
//depot/else/more/triple.c
Y mi script:
begin
paths = File.open(ARGV[0]).readlines
puts(paths)
new_paths = Array.new
paths.each { |path|
folders = path.split('/')
if ( folders.include?('..') )
num_dotdots = 0
first_dotdot = folders.index('..')
last_dotdot = folders.rindex('..')
folders.each { |item|
if ( item == '..' )
num_dotdots += 1
end
}
if ( first_dotdot and ( num_dotdots > 0 ) ) # this might be redundant?
folders.slice!(first_dotdot - num_dotdots..last_dotdot) # dependent on consecutive dotdots only
end
end
folders.map! { |elem|
if ( elem !~ /\n/ )
elem = elem + '/'
else
elem = elem
end
}
new_paths << folders.to_s
}
puts(new_paths)
end
Solución
No hay que reinventar la rueda ... File.expand_path
lo hace por usted:
[
'//depot/foo/../bar/single.c',
'//depot/foo/docs/../../other/double.c',
'//depot/foo/usr/bin/../../../else/more/triple.c'
].map {|p| File.expand_path(p) }
# ==> ["//depot/bar/single.c", "//depot/other/double.c", "//depot/else/more/triple.c"]
Otros consejos
¿Por qué no usar File.expand_path
:
irb(main):001:0> File.expand_path("//depot/foo/../bar/single.c")
=> "//depot/bar/single.c"
irb(main):002:0> File.expand_path("//depot/foo/docs/../../other/double.c")
=> "//depot/other/double.c"
irb(main):003:0> File.expand_path("//depot/foo/usr/bin/../../../else/more/triple.c")
=> "//depot/else/more/triple.c"
Para una solución de bricolaje utilizando matrices, esto viene a la mente (también funciona para sus ejemplos):
absolute = []
relative = "//depot/foo/usr/bin/../../../else/more/triple.c".split('/')
relative.each { |d| if d == '..' then absolute.pop else absolute.push(d) end }
puts absolute.join('/')
código Python:
paths = ['//depot/foo/../bar/single.c',
'//depot/foo/docs/../../other/double.c',
'//depot/foo/usr/bin/../../../else/more/triple.c']
def convert_path(path):
result = []
for item in path.split('/'):
if item == '..':
result.pop()
else:
result.append(item)
return '/'.join(result)
for path in paths:
print convert_path(path)
impresiones:
//depot/bar/single.c
//depot/other/double.c
//depot/else/more/triple.c
Se puede usar el mismo algoritmo en Ruby.