Yo podría hacer esto ciega con respecto a la conversión ruta absoluta (por caminos de depósito forzosamente) mejor?

StackOverflow https://stackoverflow.com/questions/2836825

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
¿Fue útil?

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.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top