IT이야기

Python에서 도스 경로를 구성요소로 분할하는 방법

cyworld 2022. 4. 1. 21:10
반응형

Python에서 도스 경로를 구성요소로 분할하는 방법

도스 경로를 나타내는 문자열 변수가 있음:

var = "d:\stuff\morestuff\furtherdown\THEFILE.txt"

이 문자열을 다음과 같이 나누고 싶다.

[ "d", "stuff", "morestuff", "furtherdown", "THEFILE.txt" ]

나는 사용해 본 적이 있다.split(), 그리고replace()첫 번째 백슬래시만 처리하거나 문자열에 16진수만 삽입한다.

이 문자열 변수를 어떻게든 원시 문자열로 변환해야 구문 분석할 수 있어.

이것을 하는 가장 좋은 방법은 무엇인가?

의 내용 또한 덧붙여야겠습니다.var즉, 구문 분석하려는 경로는 실제로 명령줄 쿼리의 반환 값입니다.내가 직접 생성하는 경로 데이터가 아니야.파일에 저장되어 있으며 명령줄 도구가 백슬래시를 벗어나지 않는다.

하고 싶다.

import os
path = os.path.normpath(path)
path.split(os.sep)

먼저 경로 문자열을 OS에 적합한 문자열로 표준화하십시오.그러면os.sep문자열 함수 분할에서 구분 기호로 사용하기에 안전해야 한다.

나는 사람들이 자기 길을 만지작거리다가 잘못 알아가는 바람에 여러 번 물렸다.공간, 슬래시, 백슬래시, 콜론 -- 혼란의 가능성은 끝이 없지만, 어쨌든 실수는 쉽게 일어난다.그래서 나는 용법을 고수한다.os.path, 그리고 그것을 근거로 추천한다.

(그러나 덕으로 가는 길은 가장 쉽게 가는 길이 아니며, 이것을 발견했을 때 많은 사람들은 바로 지옥으로 가는 미끄러운 길을 택하고 싶은 유혹을 받는다.그들은 언젠가는 모든 것이 산산조각이 날 때까지 깨닫지 못할 것이고, 그들은, 아니, 더 가능성이 높은 누군가는 왜 모든 것이 잘못되었는지 알아내야 하며, 누군가 슬래시와 백슬래시를 섞는 파일 이름을 만들었음이 밝혀지고, 어떤 사람들은 그 답이 "그러지 말라"고 제안한다.이 사람들처럼 굴지 마슬래시와 백슬래시를 섞은 사람을 제외하고 - 원한다면 그 사람이 될 수 있다.)

다음과 같은 드라이브와 경로+ 파일을 얻을 수 있다.

drive, path_and_file = os.path.splitdrive(path)

경로 및 파일 가져오기:

path, file = os.path.split(path_and_file)

개별 폴더 이름을 얻는 것은 특별히 편리한 것은 아니지만, 나중에 실제로 잘 작동하는 것을 찾는 즐거움을 높이는 일종의 솔직한 중간 불편함이다.

folders = []
while 1:
    path, folder = os.path.split(path)

    if folder != "":
        folders.append(folder)
    elif path != "":
        folders.append(path)

        break

folders.reverse()

(이거 터진다."\"을 시작할 때folders만약 그 길이 원래 절대적이었다면.그걸 원하지 않으면 코드를 조금 잃을 수도 있다.)

파이톤 >=3.4에서 이것은 훨씬 더 간단해졌다.이제 당신은 어떤 경로의 모든 부분을 얻는데 사용할 수 있다.

예:

>>> from pathlib import Path
>>> Path('C:/path/to/file.txt').parts
('C:\\', 'path', 'to', 'file.txt')
>>> Path(r'C:\path\to\file.txt').parts
('C:\\', 'path', 'to', 'file.txt')

Python 3의 Windows 설치에서는 사용자가 Windows 경로로 작업하고 있다고 가정하고 *nix에서는 posix 경로로 작업한다고 가정한다.이것은 보통 당신이 원하는 것이지만 만약 그렇지 않다면 당신은 수업을 이용할 수 있다.pathlib.PurePosixPath또는pathlib.PureWindowsPath필요한 경우:

>>> from pathlib import PurePosixPath, PureWindowsPath
>>> PurePosixPath('/path/to/file.txt').parts
('/', 'path', 'to', 'file.txt')
>>> PureWindowsPath(r'C:\path\to\file.txt').parts
('C:\\', 'path', 'to', 'file.txt')
>>> PureWindowsPath(r'\\host\share\path\to\file.txt').parts
('\\\\host\\share\\', 'path', 'to', 'file.txt')

편집: pathlib2에 대한 백포트를 사용할 수도 있음: pathlibathlib2

당신은 간단히 가장 많은 피토닉 접근법을 사용할 수 있다.

import os

your_path = r"d:\stuff\morestuff\furtherdown\THEFILE.txt"
path_list = your_path.split(os.sep)
print path_list

다음과 같은 이점을 누리십시오.

['d:', 'stuff', 'morestuff', 'furtherdown', 'THEFILE.txt']

여기서 단서는 사용이다.os.sep대신에'\\'또는'/', 이것이 시스템을 독립적으로 만들기 때문에.

드라이브 문자에서 콜론을 제거하려면(드라이브 문자에서 콜론을 제거하려는 이유를 알 수 없지만) 다음을 입력하십시오.

path_list[0] = path_list[0][0]

좀 더 간결한 솔루션을 위해 다음을 고려하십시오.

def split_path(p):
    a,b = os.path.split(p)
    return (split_path(a) if len(a) and len(b) else []) + [b]

여기서 문제는 애초에 어떻게 문자열을 만드느냐에서 시작된다.

a = "d:\stuff\morestuff\furtherdown\THEFILE.txt"

Python은 이 방법을 통해 다음과 같은 사례를 특별하게 다루려고 한다.\s\m\f, 그리고\T.당신의 경우\f다른 백슬래시가 올바르게 처리되는 동안 폼피드(0x0C)로 처리된다.다음 중 하나를 수행해야 한다.

b = "d:\\stuff\\morestuff\\furtherdown\\THEFILE.txt"      # doubled backslashes
c = r"d:\stuff\morestuff\furtherdown\THEFILE.txt"         # raw string, no doubling necessary

그러면 이것들 중 하나를 나누면 원하는 결과를 얻을 수 있을 거야.

나는 실제로 이 문제에 진정한 답을 줄 수는 없지만(내가 직접 하나를 찾기를 희망하며 여기 왔기 때문에), 내게는 접근방식의 차이와 언급된 모든 주의사항은 파이썬의 os.path 모듈이 내장 기능으로 이것을 절실히 필요로 한다는 가장 확실한 지표다.

발전기를 이용한 기능적 방법.

def split(path):
    (drive, head) = os.path.splitdrive(path)
    while (head != os.sep):
        (head, tail) = os.path.split(head)
        yield tail

작동 중:

>>> print([x for x in split(os.path.normpath('/path/to/filename'))])
['filename', 'to', 'path']

관한 것.mypath.split("\\")라고 표현하는 것이 좋을 것이다.mypath.split(os.sep).sep 특정의 로子:\ 윈도우의 경우를 /유닉스 등), 그리고 파이톤 빌드는 어떤 것을 사용해야 할지 알고 있다.사용한다면sep그러면 당신의 코드는 플랫폼 불가지론자가 될 것이다.

재귀적으로 할 수 있다.os.path.split현악기

import os
def parts(path):
    p,f = os.path.split(path)
    return parts(p) + [f] if f else [p]

일부 경로 문자열에 대해 테스트하고 경로 재조립os.path.join

>>> for path in [
...         r'd:\stuff\morestuff\furtherdown\THEFILE.txt',
...         '/path/to/file.txt',
...         'relative/path/to/file.txt',
...         r'C:\path\to\file.txt',
...         r'\\host\share\path\to\file.txt',
...     ]:
...     print parts(path), os.path.join(*parts(path))
... 
['d:\\', 'stuff', 'morestuff', 'furtherdown', 'THEFILE.txt'] d:\stuff\morestuff\furtherdown\THEFILE.txt
['/', 'path', 'to', 'file.txt'] /path\to\file.txt
['', 'relative', 'path', 'to', 'file.txt'] relative\path\to\file.txt
['C:\\', 'path', 'to', 'file.txt'] C:\path\to\file.txt
['\\\\', 'host', 'share', 'path', 'to', 'file.txt'] \\host\share\path\to\file.txt

목록의 첫 번째 요소는 드라이브 문자, UNC 경로 및 절대 및 상대 경로에 따라 다르게 처리해야 할 수 있다.마지막 변경[p][os.path.splitdrive(p)]드라이브 문자와 디렉터리 루트를 튜플로 분리하여 문제를 해결하십시오.

import os
def parts(path):
    p,f = os.path.split(path)
    return parts(p) + [f] if f else [os.path.splitdrive(p)]

[('d:', '\\'), 'stuff', 'morestuff', 'furtherdown', 'THEFILE.txt']
[('', '/'), 'path', 'to', 'file.txt']
[('', ''), 'relative', 'path', 'to', 'file.txt']
[('C:', '\\'), 'path', 'to', 'file.txt']
[('', '\\\\'), 'host', 'share', 'path', 'to', 'file.txt']

편집: 나는 이 답변이 사용자 1556435에 의해 위에 제시된 답변과 매우 유사하다는 것을 깨달았다.경로의 드라이브 컴포넌트 처리가 달라서 답변을 남긴다.

나한테는 효과가 있어:

>>> a=r"d:\stuff\morestuff\furtherdown\THEFILE.txt"
>>> a.split("\\")
['d:', 'stuff', 'morestuff', 'furtherdown', 'THEFILE.txt']

물론 첫 번째 구성 요소에서 결장을 제거해야 할 수도 있지만, 유지하면 경로를 다시 조립할 수 있다.

r수정자는 문자열을 "원시"로 표시하며 내장된 백슬래시가 어떻게 두 배로 증가하지 않는지 주의하십시오.

os.path.basename 함수를 사용하므로 반환된 목록에 슬래시를 추가하지 않으므로 다음을 사용한다.또한 어떤 플랫폼의 슬래시(즉, 윈도우의 슬래시)와도 작동한다. \\\\또는 유닉스의 /. 그리고 더 나아가서, 그것은 더하지 않는다.\\\\\\\\서버 경로에 사용하는 창 :)

def SplitPath( split_path ):
    pathSplit_lst   = []
    while os.path.basename(split_path):
        pathSplit_lst.append( os.path.basename(split_path) )
        split_path = os.path.dirname(split_path)
    pathSplit_lst.reverse()
    return pathSplit_lst

다음의 경우:

\\\\\\\server\\\\folder1\\\\folder2\\\\folder3\\\\folder4

다음과 같은 혜택을 누리십시오.

['server','folder1','folder2','folder3','folder4']

매우 쉽고 간단한 방법:

var.replace('\\', '/').split('/')

다른 사람들이 설명한 대로 - 당신의 문제는\문자열 리터럴/리터럴의 이스케이프 문자.OTOH, 만약 당신이 다른 소스에서 파일 경로 문자열을 가지고 있었다면(파일로부터 읽거나, 콘솔에서 읽거나, os 함수에 의해 반환됨) - '\\'나 r'\'로 분할하는 데 문제가 없었을 것이다.

그리고 다른 사람들이 제안한 것처럼, 만약 당신이 사용하길 원한다면\프로그램 리터럴에서는 복제해야 한다.\\아니면 문자 전체를 앞에 붙여야 한다.r, 그렇게.r'lite\ral'또는r"lite\ral"파서가 그걸 변환하는 걸 피하려면\, 그리고rCR(캐리지 리턴) 문자에 연결.

하지만 한 가지 더 방법이 있다 - 백슬래시를 사용하지 마라.\코드의 경로 이름!지난 세기 이래로 Windows는 슬래시를 디렉토리 구분자로 사용하는 경로 이름을 인식하고 잘 작동한다./어떻게 된 일인지 아는 사람이 많지 않아그러나 다음과 같이 작동한다.

>>> var = "d:/stuff/morestuff/furtherdown/THEFILE.txt"
>>> var.split('/')
['d:', 'stuff', 'morestuff', 'furtherdown', 'THEFILE.txt']

그런데 이렇게 하면 당신의 코드가 Unix, Windows, Mac에서 작동하게 될 것이다...왜냐하면 모두 다 사용하기 때문이다./디렉토리 구분자로...모듈의 미리 정의된 상수를 사용하지 않으려는 경우에도os.

파일이 있다고 가정해 보십시오.filedata.txt내용 포함:

d:\stuff\morestuff\furtherdown\THEFILE.txt
d:\otherstuff\something\otherfile.txt

파일 경로를 읽고 분할할 수 있음:

>>> for i in open("filedata.txt").readlines():
...     print i.strip().split("\\")
... 
['d:', 'stuff', 'morestuff', 'furtherdown', 'THEFILE.txt']
['d:', 'otherstuff', 'something', 'otherfile.txt']

re.properties는 끈보다 조금 더 많은 것을 도울 수 있다.

import re    
var = "d:\stuff\morestuff\furtherdown\THEFILE.txt"
re.split( r'[\\/]', var )
['d:', 'stuff', 'morestuff', 'furtherdown', 'THEFILE.txt']

Linux 및 Mac 경로도 지원하려면 필터(None, result)를 추가하기만 하면 된다. 따라서 해당 경로가 '//' 또는 '//'로 시작되므로 분할()에서 원하지 않는 ''을(를) 제거한다(예: '/mount/...' 또는 '/var/tmp/').

import re    
var = "/var/stuff/morestuff/furtherdown/THEFILE.txt"
result = re.split( r'[\\/]', var )
filter( None, result )
['var', 'stuff', 'morestuff', 'furtherdown', 'THEFILE.txt']

코드 라인의 아래는 다음을 처리할 수 있다.

  1. C:/경로/경로
  2. C://경로//경로
  3. C:\path\path
  4. C:\path\path

경로 = re.properties(r'[///\], 경로)

재미로 재귀 한번.

가장 우아한 대답은 아니지만 어디에서나 효과가 있어야 한다.

import os

def split_path(path):
    head = os.path.dirname(path)
    tail = os.path.basename(path)
    if head == os.path.dirname(head):
        return [tail]
    return split_path(head) + [tail]

@Mike Robins의 솔루션을 개조하여 처음부터 빈 경로 요소를 피하십시오.

def parts(path):
    p,f = os.path.split(os.path.normpath(path))
    return parts(p) + [f] if f and p else [p] if p else []

os.path.normpath()실제로 한 번만 필요하며, 재귀에 대한 별도의 입력 기능으로 수행될 수 있다.

이것이 질문에 대한 해답이 될지는 모르겠지만, 스택을 유지하고, os.path 기반 조작을 고수하며, 항목의 목록/스택을 반환하는 이 작은 기능을 쓰면서 즐거운 시간을 보냈다.

def components(path):
    ret = []
    while len(path) > 0:
        path, crust = split(path)
        ret.insert(0, crust)
    return ret
from os import path as os_path

그 다음에

def split_path_iter(string, lst):
    head, tail = os_path.split(string)
    if head == '':
        return [string] + lst
    else:
        return split_path_iter(head, [tail] + lst)

def split_path(string):
    return split_path_iter(string, [])

또는 위의 답변(더 우아함):

def split_path(string):
    head, tail = os_path.split(string)
    if head == '':
        return [string]
    else:
        return split_path(head) + [tail]

아쉽다! python os.path에는 os.path.splitall 같은 것이 없다.

어쨌든, 이것은 나에게 효과가 있다. 신용: https://www.oreilly.com/library/view/python-cookbook/0596001673/ch04s16.html

import os

a = '/media//max/Data/'

def splitall(path):
    # https://www.oreilly.com/library/view/python-cookbook/0596001673/ch04s16.html
    allparts = []
    while 1:
        parts = os.path.split(path)
        if parts[0] == path:  # sentinel for absolute paths
            allparts.insert(0, parts[0])
            break
        elif parts[1] == path: # sentinel for relative paths
            allparts.insert(0, parts[1])
            break
        else:
            path = parts[0]
            allparts.insert(0, parts[1])
    return allparts

x = splitall(a)
print(x)

z = os.path.join(*x)
print(z)

출력:

['/', 'media', 'max', 'Data', '']
/media/max/Data/

사용하다ntpath.split()

참조URL: https://stackoverflow.com/questions/3167154/how-to-split-a-dos-path-into-its-components-in-python

반응형