Ruby 相对于绝对路径转换(对于perforce depot路径),我能做得更好吗?

Ruby 相对于绝对路径转换(对于perforce depot路径),我能做得更好吗?,ruby,algorithm,relative-path,absolute-path,Ruby,Algorithm,Relative Path,Absolute Path,我需要“盲目”(即不访问文件系统,在本例中是源代码管理服务器)将一些相对路径转换为绝对路径。所以我在玩点和索引。对于那些好奇的人,我有一个由其他人的工具生成的日志文件,有时会输出相对路径,出于性能原因,我不想访问路径所在的源代码管理服务器,以检查它们是否有效,并更容易地将它们转换为绝对路径等价物 我已经经历了多次(可能是愚蠢的)迭代,试图让它正常工作-主要是在文件夹数组上迭代,并尝试在(索引)处删除和在(索引-1)处删除,但我的索引一直在增加,而我正在从我自己的下面删除数组中的元素,这对有多个点

我需要“盲目”(即不访问文件系统,在本例中是源代码管理服务器)将一些相对路径转换为绝对路径。所以我在玩点和索引。对于那些好奇的人,我有一个由其他人的工具生成的日志文件,有时会输出相对路径,出于性能原因,我不想访问路径所在的源代码管理服务器,以检查它们是否有效,并更容易地将它们转换为绝对路径等价物

我已经经历了多次(可能是愚蠢的)迭代,试图让它正常工作-主要是在文件夹数组上迭代,并尝试在(索引)处删除和在(索引-1)处删除,但我的索引一直在增加,而我正在从我自己的下面删除数组中的元素,这对有多个点的案例不起作用。任何关于改进它的一般性或特别是缺少非连续dotdot支持的提示都是受欢迎的

目前,这是我的有限的例子,但我认为它可以改进。它不能处理非连续的“..”目录,我可能正在做很多浪费(和容易出错)的事情,我可能不需要做,因为我有点黑客

我发现了很多使用其他语言转换其他类型的相对路径的例子,但没有一个适合我的情况

以下是我需要转换的示例路径:

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

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

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

致:

//仓库/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
开始
路径=文件.open(ARGV[0]).readlines
放置(路径)
新建路径=Array.new
路径。每个{路径|
文件夹=路径。拆分(“/”)
如果(文件夹。包括?(“…”))
num_dotdots=0
第一个点=folders.index(“..”)
last_dotdot=folders.rindex(“..”)
文件夹。每个{项目|
如果(项目==“…”)
num_dotdots+=1
结束
}
如果(first_dotdot和(num_dotdots>0))#这可能是多余的?
folders.slice!(first_dotdot-num_dotdots..last_dotdot)#仅依赖于连续的点
结束
结束
folders.map!{| elem|
if(elem!~/\n/)
elem=elem+'/'
其他的
元素=元素
结束
}
新路径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中使用相同的算法。

为什么不使用
文件。展开\u 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解决方案,我想到了这一点(也适用于您的示例):


让我们不要重新发明轮子…
文件。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没有出现在我为“ruby convert relative to absolute 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"]