Potrei fare questo cieco rispetto alla conversione percorso assoluto (per i percorsi depot Perforce) meglio?

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

Domanda

Ho bisogno di "alla cieca" (vale a dire senza accesso al file system, in questo caso il server di controllo del codice sorgente) convertire alcuni percorsi relativi a percorsi assoluti. Così sto giocando con dotdots e indici. Per coloro che sono curiosi ho un file di log prodotto da qualcun altro strumento che a volte uscite percorsi relativi, e per motivi di prestazioni non voglio per accedere al server di controllo di origine in cui si trovano i percorsi per controllare se sono validi e molto altro ancora facilmente convertirli in loro equivalenti percorso assoluto.

Ho passato attraverso un certo numero di iterazioni (probabilmente folli) cercando di farlo al lavoro - per lo più alcune variazioni di iterazione di matrice di cartelle e cercando delete_at (indice) e delete_at (index-1), ma il mio indice tenuto incremento mentre ero l'eliminazione di elementi della matrice da sotto di me, che non ha funzionato per i casi con più dotdots. Eventuali suggerimenti su come migliorare in generale o in particolare la mancanza di supporto dotdot non consecutive sarebbe il benvenuto.

Al momento questo sta lavorando con i miei limitati esempi, ma penso che potrebbe essere migliorata. Esso non può gestire non consecutivi '..' directory, e sto probabilmente facendo un sacco di cose inutili (e soggetti a errori) che probabilmente non ho bisogno di fare perché sono un po 'di hack.

ho trovato un sacco di esempi di conversione di altri tipi di percorsi relativi usando altre lingue, ma nessuno di loro sembrava adattarsi mia situazione.

Questi sono i miei percorsi di esempio che ho bisogno di convertire, da:

//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

E il mio 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
È stato utile?

Soluzione

Non dobbiamo reinventare la ruota ... File.expand_path che fa per voi:

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

Altri suggerimenti

Perché non usare 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"

Per una soluzione fai da te utilizzando Array, questo viene in mente (funziona anche per i vostri esempi):

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

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

stampe:

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

È possibile utilizzare lo stesso algoritmo in Ruby.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top