Pourrais-je faire aveugle par rapport à la conversion de chemin absolu (pour les chemins de dépôt Perforce) mieux?

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

Question

Je dois « aveuglément » (à savoir sans accès au système de fichiers, dans ce cas, le serveur de contrôle de code source) convertir des chemins relatifs à des chemins absolus. Donc, je joue avec dotdots et indices. Pour ceux qui sont curieux, j'ai un fichier journal produit par quelqu'un d'outil d'autre que de parfois des chemins relatifs, et pour des raisons de performance, je ne veux pas accéder au serveur de contrôle de code source où les chemins sont situés pour vérifier si elles sont valides et plus facilement les convertir à leurs équivalents de chemin absolu.

Je suis passé par plusieurs (probablement folles) itérations essayant de le faire au travail - la plupart du temps quelques variations de itérer sur le tableau de dossiers et d'essayer delete_at (index) et delete_at (index 1), mais mon index gardé incrémenter alors que je supprimait les éléments du tableau de sous moi-même, ce qui n'a pas fonctionné pour les cas avec plusieurs dotdots. Tous les conseils sur l'amélioration en général ou en particulier le manque de soutien de pointpoint non consécutifs serait la bienvenue.

Actuellement, ce travaille avec mes exemples limités, mais je pense qu'il pourrait être amélioré. Il ne peut pas gérer les répertoires non consécutifs « .. », et que je fais sans doute beaucoup de choses inutiles (et sujettes à l'erreur) que je ne doute pas besoin de faire parce que je suis un peu un hack.

Je l'ai trouvé beaucoup d'exemples de conversion d'autres types de chemins relatifs à l'aide d'autres langues, mais aucun d'entre eux semblait ma situation.

Ce sont mes exemple des chemins que je dois convertir, de:

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

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

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

à:

//depot/bar/single.c

//depot/other/double.c

//depot/else/more/triple.c

Et mon 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
Était-ce utile?

La solution

Il ne faut pas réinventer la roue ... File.expand_path fait pour vous:

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

Autres conseils

Pourquoi ne pas utiliser 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"

Pour une solution DIY en utilisant des tableaux, cela vient à l'esprit (fonctionne aussi pour vos exemples):

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('/')

code 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)

impressions:

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

Vous pouvez utiliser le même algorithme Ruby.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top