문자열의 왼쪽 부분을 제거하는 방법?


144

나는 문자열 등을 검색 파일이 몇 가지 간단한 파이썬 코드가 path=c:\pathc:\path일부가 다를 수 있습니다. 현재 코드는 다음과 같습니다

def find_path(i_file):
    lines = open(i_file).readlines()
    for line in lines:
        if line.startswith("Path="):
            return # what to do here in order to get line content after "Path=" ?

텍스트를 얻는 간단한 방법은 무엇입니까 Path=?


"Path ="로 시작하는 파일 내에서 첫 번째 행에서 복귀한다는 점에 유의하십시오. 이 게시물에 대한 다른 답변도 있습니다. 그러나 파일이 DOS 배치 파일과 같은 경우 실제로 "일괄 처리"또는 명령 파일이 조건으로 채워지지 않은지 여부에 따라 해당 파일에서 마지막 행이 발생할 수 있습니다.
DevPlayer

답변:



196

문자열이 고정되어 있으면 간단하게 사용할 수 있습니다.

if line.startswith("Path="):
    return line[5:]

이것은 문자열에서 위치 5부터 모든 것을 제공합니다 (문자열은 시퀀스이므로 이러한 시퀀스 연산자도 여기에서 작동합니다).

또는 처음에 줄을 나눌 수 있습니다 =.

if "=" in line:
    param, value = line.split("=",1)

그런 다음 param은 "Path"이고 value는 첫 번째 = 이후의 나머지입니다.


3
split 방법의 +1은 len (접두사)에서 수동 슬라이싱의 약간의 추악함을 피합니다.
bobince

1
입력 내용이 모두 "something = somethingelse"형식이 아닌 경우에도 발생합니다.
Dan Olson

1
그렇기 때문에 조건을 앞에 두어 "="가 문자열에있는 경우에만 사용됩니다. 그렇지 않으면 split () 결과의 길이와 == 2인지 테스트 할 수도 있습니다.
MrTopf

7
Dan Olson과 같이 split구분 기호가 없으면 예외가 발생 한다고 말합니다 . partition더 안정적이며 문자열을 분할하고 항상 사전, 구분 기호 및 사후 내용이있는 3 요소 튜플을 반환합니다 (일부 ''구분 기호가없는 경우도 있음). 예, value = line.partition('=').
Anders Johansson

1
구분 기호가 없으면 Split은 예외를 throw하지 않으며 전체 문자열이 포함 된 목록을 반환합니다. 적어도 python 2.7 이하
Maxim

122

문자열에서 접두사 제거

# ...
if line.startswith(prefix):
   return line[len(prefix):]

를 통해 분리기의 첫 번째 발생에서 분리 str.partition()

def findvar(filename, varname="Path", sep="=") :
    for line in open(filename):
        if line.startswith(varname + sep):
           head, sep_, tail = line.partition(sep) # instead of `str.split()`
           assert head == varname
           assert sep_ == sep
           return tail

ConfigParser로 INI와 유사한 파일 구문 분석

from ConfigParser import SafeConfigParser
config = SafeConfigParser()
config.read(filename) # requires section headers to be present

path = config.get(section, 'path', raw=1) # case-insensitive, no interpolation

다른 옵션


1
드문 이유는 4 개 대신 3 개의 공백을 들여 쓰기하는 것입니다.
Bob Stein

25
def remove_prefix(text, prefix):
    return text[len(prefix):] if text.startswith(prefix) else text

1
"else text"를 "else False"또는 "else None"또는 -type-으로 바꾸거나 파일의 행이 "Path ="로 시작하지 않았 음을 나타 내기 위해 반환하려는 것이기 때문에이 방법이 마음에 듭니다. 개인적으로 저는 삼항 연산자를 괄호로 묶어 시각적으로 눈에 띄는 것을 좋아합니다.
DevPlayer

19

일반적으로 슬라이싱 (조건부 또는 비 조건부)의 경우 동료가 최근에 제안한 것을 선호합니다. 빈 문자열로 교체하십시오. 코드를 더 쉽게 읽을 수 있고, 코드가 적고 (때로는) 잘못된 문자 수를 지정할 위험이 줄어 듭니다. 확인; 나는 파이썬을 사용하지 않지만 다른 언어에서는이 접근법을 선호합니다.

rightmost = full_path.replace('Path=', '', 1)

또는-이 게시물에 대한 첫 번째 주석까지 후속 조치- 행으로 시작 하는 경우 에만 수행 해야하는 경우Path :

rightmost = re.compile('^Path=').sub('', full_path)

위에서 제안 된 것 중 일부와의 주요 차이점은 관련된 "마법 번호"(5)가없고 ' 5' 문자열 ' Path='을 모두 지정할 필요가 없다는 것입니다. 즉, 코드 유지 관리에서이 방법을 선호합니다 관점.


작동하지 않습니다 : 'c = Path = a'.replace ( "Path =", "", 1)->'c = a '.
jfs

3
"Path ="로 시작하는 문자열의 원래 요구 사항을 충족하지 않습니다.
강아지

1
정규식 코드를 그냥로 바꿀 수 있습니다 rightmost = re.sub('^Path=', '', fullPath). 이 compile()방법 의 목적은 컴파일 된 객체를 재사용하면 작업 속도를 높이는 것이지만 사용 후에는 버릴 수 있기 때문에 여기서는 아무런 영향을 미치지 않습니다. 어쨌든이 최적화에 대해 걱정할 가치가 없습니다.
Jim Oldfield

13

pop색인 생성을 선호 합니다 [-1].

value = line.split("Path=", 1).pop()

value = line.split("Path=", 1)[1]
param, value = line.split("Path=", 1)

2
"마법의 숫자"가없는 좋은 대안. startswith이미 테스트되었으므로 split"아무것도"이전과 이후의 모든 것을 나눌 것이므로 이것이 작동한다는 점에 주목할 가치가 있습니다. split("Path=", 1)접두사가 문자열에 나중에 다시 나타나는 경우 더 정확하지만 마법 번호를 다시 소개합니다.
quornian

1
(매우 중요한) 이전 주석의 짧은 버전 : startswith ()로 먼저 테스트하는 경우에만 작동합니다.
MarcH

12

아니면 왜 안돼

if line.startswith(prefix):
    return line.replace(prefix, '', 1)

5

어때요 ..

>>> line = r'path=c:\path'
>>> line.partition('path=')
('', 'path=', 'c:\\path')

이 삼중 항은 head, separator 및 tail 입니다.


모든 경우에 동일한 방식으로 작동하지는 않습니다. 구분 기호가 있으면 결과는 세 번째 항목입니다. 그렇지 않으면 결과는 첫 번째 항목입니다.
Ioannis Filippidis

5

내가 생각할 수있는 가장 간단한 방법은 슬라이싱입니다.

def find_path(i_file): 
    lines = open(i_file).readlines() 
    for line in lines: 
        if line.startswith("Path=") : 
            return line[5:]

슬라이스 표기법에 대한 간단한 참고 사항으로 일반적인 색인 대신 두 개의 색인을 사용합니다. 첫 번째 인덱스는 슬라이스 에 포함하려는 시퀀스의 첫 번째 요소를 나타내고 마지막 인덱스는 슬라이스에 포함하려는 마지막 요소 바로 다음의 인덱스입니다.
예 :

sequence_obj[first_index:last_index]

슬라이스는 사이의 모든 요소로 구성 first_index하고 last_index, 포함 first_index하지 last_index. 첫 번째 인덱스를 생략하면 시퀀스의 시작으로 기본 설정됩니다. 마지막 인덱스를 생략하면 시퀀스의 마지막 요소까지 모든 요소가 포함됩니다. 음수 지수도 허용됩니다. 주제를 자세히 알아 보려면 Google을 사용하십시오.


4
>>> import re

>>> p = re.compile(r'path=(.*)', re.IGNORECASE)

>>> path = "path=c:\path"

>>> re.match(p, path).group(1)
'c:\\path'

1. r''Windows 경로에 문자열을 사용하십시오 . 2. re.match()None을 반환 할 수 있음
jfs

3

여기에 언급되지 않은 또 하나의 간단한 라이너.

value = line.split("Path=", 1)[-1]

이것은 다양한 엣지 케이스에서도 올바르게 작동합니다.

>>> print("prefixfoobar".split("foo", 1)[-1])
"bar"

>>> print("foofoobar".split("foo", 1)[-1])
"foobar"

>>> print("foobar".split("foo", 1)[-1])
"bar"

>>> print("bar".split("foo", 1)[-1])
"bar"

>>> print("".split("foo", 1)[-1])
""


1

line[5:]원하는 부분 문자열을 제공합니다. 검색 도입 '슬라이스 표기법'과 모양을


1

목록 이해력을 알고있는 경우 :

lines = [line[5:] for line in file.readlines() if line[:5] == "Path="]

편집 line.startswith(...)속도가 10 배 빠릅니다. 내 테스트에서 이것을 확인하지 못했습니다. 주장을 뒷받침하는 증거가 제공되면이를 변경해 보시기 바랍니다.
Matthew Schinckel

0

팝 버전이 옳지 않았습니다. 나는 당신이 원하는 것 같아요 :

>>> print('foofoobar'.split('foo', 1).pop())
foobar

0

탈출과 함께 정규 표현식을 사용하지 않는 이유는 무엇입니까? ^줄의 처음 부분과 re.MULTILINE일치하고 각 줄에서 일치합니다. re.escape일치하는 것이 정확합니다.

>>> print(re.sub('^' + re.escape('path='), repl='', string='path=c:\path\nd:\path2', flags=re.MULTILINE))
c:\path
d:\path2

0

다음 코드를 시도하십시오

if line.startswith("Path="): return line[5:]

1
답변과 수락 된 답변의 차이점은 무엇입니까? 나는 그것이 다른 대답의 첫 부분에 있음을 알았습니다.
eyllanesc 2016 년

-1

나는 이것이 당신이 정확하게 찾고있는 것 같아요

    def findPath(i_file) :
        lines = open( i_file ).readlines()
        for line in lines :
            if line.startswith( "Path=" ):
                output_line=line[(line.find("Path=")+len("Path=")):]
                return output_line

-1

함수를 작성하지 않아도 목록에 따라 분할됩니다 (이 경우 'Mr. | Dr. | Mrs.'). [1]로 분할 한 후 모든 항목을 선택한 다음 다시 분할하여 요소를 가져옵니다. 아래의 경우 'Morris'가 반환됩니다.

re.split('Mr.|Dr.|Mrs.', 'Mr. Morgan Morris')[1].split()[1]

-1

이것은 기술에서 다른 답변과 매우 유사하지만 반복되는 문자열 작업이 없으며 접두사가 있는지 여부를 알 수 있으며 여전히 읽을 수 있습니다.

parts = the_string.split(prefix_to_remove, 1):
    if len(parts) == 2:
        #  do things with parts[1]
        pass
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.