Eu poderia fazer esse cego em relação à conversão absoluta do caminho (para os caminhos de depósito de Perforce) melhor?

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

Pergunta

Eu preciso "cegamente" (ou seja, sem acesso ao sistema de arquivos, neste caso o servidor de controle de origem) converte alguns caminhos relativos em caminhos absolutos. Então, eu estou brincando com Dotdots e índices. Para aqueles que estão curiosos, tenho um arquivo de log produzido pela ferramenta de outra pessoa que às vezes gera caminhos relativos e, por motivos de desempenho, não quero acessar o servidor de controle de origem onde os caminhos estão localizados para verificar se são válidos e mais converte -os facilmente em seus equivalentes absolutos.

Eu passei por várias iterações (provavelmente tolas) tentando fazer com que funcione - principalmente algumas variações de iterar sobre a matriz de pastas e tentar excluir_at (índice) e delete_at (índice -1), mas meu índice continuou incrementando enquanto Eu estava excluindo elementos da matriz fora de mim, o que não funcionou para casos com vários pontos. Quaisquer dicas sobre como melhorá-lo em geral ou especificamente a falta de suporte do DOTDOT não consecutivo seria bem-vindo.

Atualmente, isso está trabalhando com meus exemplos limitados, mas acho que poderia ser melhorado. Não pode lidar com diretórios não consecutivos '..', e provavelmente estou fazendo muitas coisas desperdiçadas (e propensas a erros) que provavelmente não preciso fazer porque sou um pouco hackeado.

Encontrei muitos exemplos de conversão de outros tipos de caminhos relativos usando outros idiomas, mas nenhum deles parecia se encaixar na minha situação.

Estes são os meus caminhos de exemplo que eu preciso converter, de:

//depot/foo/../bar/single.c

//depot/foo/docs/../../other/double.c

//depot/foo/usr/bin/../../../else/more/triple.c

para:

//depot/bar/single.c

//depot/other/double.c

//depot/else/more/triple.c

E meu 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
Foi útil?

Solução

Não vamos reinventar a roda ... File.expand_path Faz isso por você:

[
  '//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"]

Outras dicas

Por que não apenas 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 uma solução de bricolage usando matrizes, isso vem à mente (também funciona para seus exemplos):

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)

impressões:

//depot/bar/single.c
//depot/other/double.c
//depot/else/more/triple.c

Você pode usar o mesmo algoritmo em Ruby.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top