如何去掉字符串的左侧部分?

173

我有一些简单的Python代码,用于在文件中搜索一个字符串,例如path=c:\path,其中c:\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
21个回答

210

如果字符串是固定的,你可以简单地使用:

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

这将从字符串的第5个位置开始,返回该位置及其后面的所有内容(由于字符串也是序列,因此这些序列运算符在此处也适用)。

或者您可以在第一个=处将该行拆分:

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

参数为 "Path",值为第一个等号后面的其余部分。


5
赞成使用split方法,避免手动切片时关于len(prefix)的微小不雅之处。 - bobince
1
但是如果您的输入不全是“something=somethingelse”的形式,它也会抛出异常。 - Dan Olson
1
这就是为什么我把条件放在前面,这样只有在字符串中出现 "=" 时才会使用它。否则,您还可以测试 split() 的结果长度是否等于2。 - MrTopf
8
Dan Olson说,如果分隔符不存在,split会抛出异常。而partition更稳定,它也能将字符串分割,且总是返回一个由三个元素组成的元组,包括前缀、分隔符和后缀内容(如果分隔符不存在,则其中一些可能为'')。例如,value = line.partition('=') - Anders Johansson
1
如果分隔符不存在,split()函数不会抛出异常,而是返回一个包含整个字符串的列表。至少在Python 2.7下是这样。 - Maxim
显示剩余2条评论

135

从字符串中删除前缀

# ...
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
缩进三个空格而不是四个的罕见原因。 - Bob Stein

98

Python 3.9 开始,您可以使用 removeprefix

'Path=helloworld'.removeprefix('Path=')
# 'helloworld'

43

Python 3.9+

text.removeprefix(prefix)

任何Python版本:

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

1
我喜欢这个,因为你可以用“else False”或“else None”或任何你想要返回的-type-来替换“else text”,以指示文件中的行没有以“Path =”开头。个人而言,我喜欢用括号将我的三元运算符括起来,以在视觉上突出显示。 - DevPlayer
有用的一行代码:remove_prefix = lambda text, prefix: text[len(prefix):] if text.startswith(prefix) else text - Basj

21

对于通用的切片(有条件或无条件),我更喜欢最近一位同事提出的建议; 使用替换为空字符串。代码更易读,代码量更少(有时),并且导致指定错误数量字符的风险更小。好的; 我不使用Python,但在其他语言中,我更喜欢这种方法:

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=”开头。 - Puppy
2
你可以用rightmost = re.sub('^Path=', '', fullPath)来替换正则表达式代码。compile()方法的目的是为了让重复使用编译后的对象更快,但由于你在使用后就抛弃了它,所以在这里没有任何效果。通常情况下,不值得担心这种优化。 - Jim Oldfield
如果前缀包含特殊字符,我会在其中添加 re.escape。例如:re.compile('^' + re.escape('Path=')) - Cristian Ciupitu

15

我更喜欢使用pop而不是索引[-1]

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

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

2
很好的替代方法,没有使用"魔法数字"。值得注意的是,这个方法有效是因为startswith已经被测试过了,所以split将在"nothing"前和后面分割所有内容。split("Path=", 1)更精确(以防前缀在字符串中再次出现),但会重新引入一个"魔法数字"。 - quornian
1
非常重要的先前评论的简短版本:仅当您首先使用startswith()进行测试时,此方法才有效。 - MarcH

12

或者为什么不呢?

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

6
我能想到的最简单的方法是使用切片:

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_indexlast_index之间的所有元素,包括first_index但不包括last_index。如果省略第一个索引,则默认为序列的开头。如果省略最后一个索引,则包括序列中的所有元素直到最后一个元素。也可以使用负索引。使用谷歌了解更多有关主题的信息。

5

这里还有一个简单的一行代码,尚未被提及:

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])
""

5

怎么样...

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

输出:

('', 'path=', 'c:\\path')

这个三元组是头部,分隔符和尾部


2
这种情况并非总是以相同的方式工作。如果分隔符存在,则结果为第三项。否则,结果为第一项。 - 0 _
你还有第三种情况,即分隔符在中间的情况:"manpath=c:\path" - Troy Daniels

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接