Могу ли я сделать этот слепой относительно абсолютной преобразования пути (для Perforce Paths Paths) лучше?

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

Вопрос

Мне нужно «слепо» (то есть без доступа к файловой системе, в этом случае сервер управления источником) преобразуют некоторые относительные пути к абсолютному пути. Так что я играю с дотдотами и индексами. Для тех, кто любопытно, у меня есть файл журнала, созданный чужом инструментом, который иногда выводит относительные пути, и по причинам производительности я не хочу получить доступ к серверу исходника, где пути расположены, чтобы проверить, они действительны и другие легко преобразовать их в свои эквиваленты абсолютного пути.

Я прошел через ряд (вероятно, глупых) итераций, пытающихся заставить его работать - в основном несколько вариаций итерации по массиву папок и попытки delete_at (индекс) и delete_at (index-1), но мой индекс продолжал увеличивать Я удалял элементы массива из-под себя, который не работал в случаях с несколькими дотуды. Любые советы по улучшению его в целом или в частности, отсутствие не последовательной поддержки DotDot.

В настоящее время это работает с моими ограниченными примерами, но я думаю, что это может быть улучшено. Это не может справиться с не последовательными катаниями .. ..

Я нашел много примеров преобразования других типов относительных путей, используя другие языки, но ни один из них не соответствует моей ситуации.

Это мои примерки, которыми мне нужно преобразовать, от:

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

И мой скрипт:

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
Это было полезно?

Решение

Давайте не переимененным колесом ... File.expand_path Это для вас:

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

Другие советы

Почему бы просто не использовать 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"

Для решения DIY используют массивы, это приходит в голову (также работает для ваших примеров):

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

Код 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)

Печать:

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

Вы можете использовать один и тот же алгоритм в Ruby.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top