我可以更好地相对于绝对路径转换(对于 perforce depot 路径)进行盲目操作吗?

发布于 2024-09-01 10:28:22 字数 1580 浏览 6 评论 0原文

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

我已经经历了多次(可能是愚蠢的)迭代,试图让它工作 - 主要是迭代文件夹数组并尝试delete_at(index)和delete_at(index-1)的一些变化,但我的索引不断增加,而我正在从自己下面删除数组的元素,这对于具有多个点的情况不起作用。任何关于总体改进或特别是缺乏非连续点点支持的提示都将受到欢迎。

目前,这仅适用于我有限的示例,但我认为它可以改进。它无法处理非连续的“..”目录,而且我可能做了很多浪费(且容易出错)的事情,而这些事情我可能不需要做,因为我有点黑客。

我发现了很多使用其他语言转换其他类型的相对路径的示例,但它们似乎都不适合我的情况。

这些是我需要转换的示例路径,来自:

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

I need to "blindly" (i.e. without access to the filesystem, in this case the source control server) convert some relative paths to absolute paths. So I'm playing with dotdots and indices. For those that are curious I have a log file produced by someone else's tool that sometimes outputs relative paths, and for performance reasons I don't want to access the source control server where the paths are located to check if they're valid and more easily convert them to their absolute path equivalents.

I've gone through a number of (probably foolish) iterations trying to get it to work - mostly a few variations of iterating over the array of folders and trying delete_at(index) and delete_at(index-1) but my index kept incrementing while I was deleting elements of the array out from under myself, which didn't work for cases with multiple dotdots. Any tips on improving it in general or specifically the lack of non-consecutive dotdot support would be welcome.

Currently this is working with my limited examples, but I think it could be improved. It can't handle non-consecutive '..' directories, and I am probably doing a lot of wasteful (and error-prone) things that I probably don't need to do because I'm a bit of a hack.

I've found a lot of examples of converting other types of relative paths using other languages, but none of them seemed to fit my situation.

These are my example paths that I need to convert, from:

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

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

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

to:

//depot/bar/single.c

//depot/other/double.c

//depot/else/more/triple.c

And my 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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

仙女山的月亮 2024-09-08 10:28:22

我们不要重新发明轮子... 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"]

Let's not reinvent the wheel... File.expand_path does that for you:

[
  '//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"]
意中人 2024-09-08 10:28:22

为什么不直接使用 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('/')

Why not just use 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"

For a DIY solution using Arrays, this comes to mind (also works for your examples):

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('/')
苏大泽ㄣ 2024-09-08 10:28:22

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)

prints:

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

您可以在 Ruby 中使用相同的算法。

Python code:

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)

prints:

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

You can use the same algorithm in Ruby.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文