2014-12-02 4 views
3

Есть ли быстрый способ заменить часть пути в python?заменить часть пути - python

, например:

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

не знаю начало пути (/abc/dfg/), так что я бы очень хотел сказать питона, чтобы сохранить все, что происходит после того, как /ghi/ (включительно) и заменить все, прежде чем /ghi/ с /jkl/mno/:

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

ответ

1

Вы можете использовать индекс 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' 
+0

спасибо за downvote, высоко оценили –

3
>>> 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' 
+1

Извините, забыл упомянуть t Я не знаю, что такое начало пути, поэтому в идеале я хотел бы сказать python, чтобы выбрать только часть пути, начиная с/ghi/и заменить все, что приходит раньше, с помощью/jkl/mno/, Возможно ли это как-то? – HappyPy

+0

Это может быть неоднозначным, хотя, если у вас есть 'foo/bar/foo/folder/f.txt' и вы хотите начать с' foo', что это за 'foo'? Вы хотя бы знаете, как далеко вы хотите идти? как всегда будет одна папка вверх от места файла? – CoryKramer

+0

Да, я уверен, что в пути нет повторяющихся имен папок. Таким образом, это будет своего рода раскол.Я хочу, чтобы python выбирал все из '/ ghi /' (в моем примере - /ghi/f.txt) и заменил все, что приходит раньше, с/jkl/mno /. – HappyPy

8

Если вы используете Python 3.4+, или готовы установить backport, рассмотреть вопрос об использовании pathlib вместо os.path:

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

Если вы просто хотите придерживаться 2.7 или 3.3 stdlib, нет direct способ сделать это, но вы можете получить эквивалент parts, перейдя по ссылке os.path.split. Например, сохраняя каждый компонент пути до тех пор, пока вы не найдете первый ghi, а затем вставьте новый префикс, замените все до последнего ghi (если вы хотите заменить все до сначала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.

+0

pathlib выглядит великолепно, предположим, что в Python 2.7 нет эквивалента? – HappyPy

+0

@HappyPy: Да, есть. Не в stdlib, но, как и многие новые функции 3.x, в PyPI есть [полуофициальный backport] (https://pypi.python.org/pypi/pathlib2/), который имеет все функции которые имеют смысл в 2.x. (Я считаю, что это означает все, кроме вещей, связанных с конвертированием в имена байтов на основе локали в именах Unix и Unicode str в Windows, вместо этого вы просто получаете равную неуказанную строку на обеих платформах.) – abarnert

+0

Для python> 3.4: вам нужно сделать 'import pathlib' и первая строка примера должны быть:' p = pathlib.Path (old_path) 'вместо' path = pathlib.Path (old_path) '. Потому что на него ссылаются как 'p' в следующих строках. [Кстати: пример очень помог!] – klaas

0

Довольно наивный подход, но делает работу:

Функция:

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

Пример:

>>> replace_path(s, '/ghi/', '/jkl/mno') 
'/jkl/mno/ghi/f.txt' 
>>> replace_path(s, '/whatever/', '/jkl/mno') 
'/abc/dfg/ghi/f.txt' 
Смежные вопросы