【问题标题】:replace part of path - python替换路径的一部分 - python
【发布时间】:2015-01-31 05:58:00
【问题描述】:

有没有一种快速的方法来替换 python 中的部分路径?

例如:

old_path='/abc/dfg/ghi/f.txt'

我不知道路径的开头 (/abc/dfg/),所以我真正想告诉 python 保留 /ghi/(包括)之后的所有内容并将/ghi/ 之前的所有内容替换为 @ 987654325@:

>>> new_path
    '/jkl/mno/ghi/f.txt/'

【问题讨论】:

    标签: python replace path


    【解决方案1】:

    如果您使用的是 Python 3.4+,或者愿意安装 backport,请考虑使用 pathlib 而不是 os.path

    path = pathlib.Path(old_path)
    index = path.parts.index('ghi')
    new_path = pathlib.Path('/jkl/mno').joinpath(*path.parts[index:])
    

    如果您只想坚持使用 2.7 或 3.3 标准库,则没有 直接 方法可以做到这一点,但您可以通过循环 os.path.split 获得等效于 parts 的方法。例如,保留每个路径组件直到找到第一个 ghi,然后添加新前缀,将替换最后一个 ghi 之前的所有内容(如果您想替换 first 之前的所有内容ghi,改东西不难):

    path = old_path
    new_path = ''
    while True:
        path, base = os.path.split(path)
        new_path = os.path.join(base, new_path)
        if base == 'ghi':
            break
    new_path = os.path.join('/jkl/mno', new_path)
    

    这有点笨拙,因此您可能需要考虑编写一个简单的函数,为您提供路径组件的列表或元组,因此您可以使用find,然后将它们重新组合在一起,就像pathlib 版本。

    【讨论】:

    • pathlib 看起来不错,假设在 Python 2.7 中没有等价物?
    • @HappyPy:是的,有。不在标准库中,但与 3.x 的许多新功能一样,PyPI 上有一个semi-official backport,它具有 2.x 中有意义的所有功能。 (我相信这意味着除了关于在 Unix 上转换为基于语言环境的字节名称和在 Windows 上转换为 Unicode str 名称的东西之外的所有内容;相反,您只会在两个平台上得到普通的未指定 str 。)
    • 对于python >3.4:你必须做一个import pathlib,并且示例的第一行应该是:p = pathlib.Path(old_path)而不是path = pathlib.Path(old_path)。因为它在以下几行中被引用为p。 [顺便说一句:这个例子有很大帮助!]
    【解决方案2】:
    >>> import os.path
    >>> old_path='/abc/dfg/ghi/f.txt'
    

    首先使用os.path.relpath从您选择的起始目录中获取相对路径

    >>> rel = os.path.relpath(old_path, '/abc/dfg/')
    >>> rel
    'ghi\\f.txt'
    

    然后使用os.path.join将路径的新第一部分添加到此相对路径

    >>> new_path = os.path.join('jkl\mno', rel)
    >>> new_path
    'jkl\\mno\\ghi\\f.txt'
    

    【讨论】:

    • 对不起,忘了说我不知道​​路径的开头是什么,所以理想情况下我希望能够告诉 python 只选择从 /ghi 开始的路径部分/ 并用 /jkl/mno/ 替换之前的任何内容。这有可能吗?
    • 这可能有点模棱两可,如果你有foo/bar/foo/folder/f.txt 并且想从foo 开始,那是foo 呢?你至少知道你想走多远吗?喜欢它总是比文件位置高一个文件夹吗?
    • 是的,我确定路径中没有重复的文件夹名称。所以,这将是一种分裂。我希望 python 从 '/ghi/' 中选择所有内容(在我的示例中是 /ghi/f.txt)并用 /jkl/mno/ 替换之前的所有内容。
    【解决方案3】:

    可以使用ghi的索引:

    old_path.replace(old_path[:old_path.index("ghi")],"/jkl/mno/")
    In [4]: old_path.replace(old_path[:old_path.index("ghi")],"/jkl/mno/" )
    Out[4]: '/jkl/mno/ghi/f.txt'
    

    【讨论】:

    • 我没有投反对票,但这不是一个很好的答案 TBH。如果在前缀中重复序列“ghi”怎么办?例如,它不适用于/fooghi/bar/ghi/baz。先拆分成部分可能会更好。
    • @TheDataScientician,OP 想要替换路径中的完整目录,即/ghi/。替换目录名称中的子字符串是完全不同的事情。
    【解决方案4】:

    一种相当幼稚的方法,但确实有效:

    功能:

    def replace_path(path, frm, to):
        pre, match, post = path.rpartition(frm)
        return ''.join((to if match else pre, match, post))
    

    例子:

    >>> s = '/abc/dfg/ghi/f.txt'
    >>> replace_path(s, '/ghi/', '/jkl/mno')
    '/jkl/mno/ghi/f.txt'
    >>> replace_path(s, '/whatever/', '/jkl/mno')
    '/abc/dfg/ghi/f.txt'
    

    【讨论】:

    • 给我 NameError: name 's' 没有定义。用 path 替换 s 会给我一个虚假的路径。
    • 现在应该修复,这是函数 replace_path() 中的一个小错字:“s”而不是“path”。
    猜你喜欢
    • 1970-01-01
    • 2013-12-01
    • 2023-01-04
    • 2019-04-15
    • 2021-09-06
    • 2019-04-22
    • 2020-10-04
    • 2019-11-02
    • 1970-01-01
    相关资源
    最近更新 更多