【问题标题】:How to remove the left part of a string?如何删除字符串的左侧部分?
【发布时间】:2010-10-10 15:22:48
【问题描述】:

我有一些简单的 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 批处理文件,您实际上可能希望此类文件的最后一行出现,具体取决于“批处理”或命令文件是否未填充条件。

标签: python string


【解决方案1】:

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

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

它为您提供字符串中从位置 5 开始的所有内容(字符串也是一个序列,因此这些序列运算符也可以在这里工作)。

或者你可以在第一个=处分行:

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

那么参数是“路径”,值是第一个 = 之后的其余部分。

【讨论】:

  • +1为split方法,避免len(prefix)上手动切片的轻微丑陋。
  • 但如果您的输入并非全部采用“something=somethingelse”形式,也会抛出。
  • 这就是为什么我把条件放在前面,所以它只在字符串中有“=”时使用。否则,您还可以测试 split() 结果的长度以及是否为 ==2。
  • 就像 Dan Olson 所说,如果分隔符不存在,split 会抛出异常。 partition 更稳定,它还拆分一个字符串,always 返回一个包含前置、定界符和后置内容的三元素元组(如果定界符是,其中一些可能是 ''不存在)。例如,value = line.partition('=')
  • 如果分隔符不存在,Split 不会抛出异常,它会返回一个包含整个字符串的列表。至少在python 2.7下
【解决方案2】:

从字符串中删除前缀

# ...
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

其他选项

【讨论】:

  • 缩进三个空格而不是四个空格的罕见原因。
【解决方案3】:

Python 3.9开始,可以使用removeprefix

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

【讨论】:

    【解决方案4】:

    任何 Python 版本:

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

    Python 3.9+

    text.removeprefix(prefix)
    

    【讨论】:

    • 我喜欢这个,因为您可以将“else text”替换为“else False”或“else None”或您想要返回的任何类型 - 以表明文件中的行没有开始与“路径=”。就我个人而言,我喜欢用括号括住我的三元运算符,以便在视觉上脱颖而出。
    【解决方案5】:

    一般来说,对于切片(条件或非条件),我更喜欢同事最近提出的建议;使用空字符串替换。更容易阅读代码,更少的代码(有时)和更少的指定错误字符数的风险。好的;我不使用 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'。
    • 不符合原字符串“Path="开头的要求。
    • 您可以只用rightmost = re.sub('^Path=', '', fullPath) 替换正则表达式代码。 compile() 方法的目的是如果你重用编译的对象,可以让事情变得更快,但是由于你使用后将其丢弃,所以无论如何它在这里没有任何作用。无论如何,通常不必担心这种优化。
    • 如果前缀包含特殊字符,我会添加 re.escape 进行混合。即re.compile('^' + re.escape('Path='))
    【解决方案6】:

    比起索引[-1],我更喜欢pop

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

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

    【讨论】:

    • 没有“幻数”的好选择。值得注意的是,这是有效的,因为startswith 已经过测试,所以split 将在之前划分“无”,之后划分其他所有内容。 split("Path=", 1) 更精确(以防前缀在字符串中稍后再次出现)但重新引入了一个幻数。
    • (非常重要的)先前评论的较短版本:仅当您首先使用startswith() 进行测试时才有效。
    【解决方案7】:

    或者为什么不

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

    【讨论】:

      【解决方案8】:

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

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

      关于切片符号的快速说明,它使用两个索引而不是通常的索引。第一个索引表示您要包含在 slice 中的序列的第一个元素,最后一个索引是您希望包含在切片中的最后一个元素之后的索引。
      例如:

      sequence_obj[first_index:last_index]
      

      切片由first_indexlast_index 之间的所有元素组成,包括first_index 而不是last_index。如果省略第一个索引,则默认为序列的开头。如果省略最后一个索引,则它包括序列中最后一个元素之前的所有元素。也允许使用负索引。使用 Google 了解有关该主题的更多信息。

      【讨论】:

        【解决方案9】:
        >>> import re
        
        >>> p = re.compile(r'path=(.*)', re.IGNORECASE)
        
        >>> path = "path=c:\path"
        
        >>> re.match(p, path).group(1)
        'c:\\path'
        

        【讨论】:

        • 1.对 Windows 路径使用 r'' 字符串。 2.re.match()可能返回无
        【解决方案10】:

        这里没有提到的另一个简单的单行:

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

        【讨论】:

          【解决方案11】:

          怎么样..

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

          这个三元组是head, separator, and tail

          【讨论】:

          • 这并不是在所有情况下都以相同的方式工作。如果存在分隔符,则结果是第三项。否则,结果为第一项。
          【解决方案12】:
          line[5:]
          

          在前五个之后给你字符。

          【讨论】:

            【解决方案13】:

            removeprefix()removesuffix()Python 3.9 中添加了字符串方法,原因是与传递给它们的参数的 lstriprstrip 解释相关的问题。阅读PEP 616了解更多详情。

            # in python 3.9
            >>> s = 'python_390a6'
            
            # apply removeprefix()
            >>> s.removeprefix('python_')
            '390a6'
            
            # apply removesuffix()
            >>> s = 'python.exe'
            >>> s.removesuffix('.exe')
            'python'
            
            # in python 3.8 or before
            >>> s = 'python_390a6'
            >>> s.lstrip('python_')
            '390a6'
            
            >>> s = 'python.exe'
            >>> s.rstrip('.exe')
            'python'
            

            removesuffix 带有列表的示例:

            plurals = ['cars', 'phones', 'stars', 'books']
            suffix = 's'
            
            for plural in plurals:
                print(plural.removesuffix(suffix))
            

            输出:

            car
            phone
            star
            book
            

            removeprefix 带有列表的示例:

            places = ['New York', 'New Zealand', 'New Delhi', 'New Now']
            
            shortened = [place.removeprefix('New ') for place in places]
            print(shortened)
            

            输出:

            ['York', 'Zealand', 'Delhi', 'Now']
            

            【讨论】:

              【解决方案14】:

              line[5:] 将给出你想要的子字符串。搜索 introduction 并查找“切片表示法”

              【讨论】:

                【解决方案15】:

                如果你知道列表推导:

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

                【讨论】:

                • 有一个编辑建议 line.startswith(...) 快 10 倍。我的测试没有证实这一点。如果提供了支持该断言的证据,我们很乐意更改它。
                【解决方案16】:

                为什么不使用带有转义的正则表达式? ^ 匹配一行的开头部分,re.MULTILINE 匹配每一行。 re.escape 确保匹配准确。

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

                【讨论】:

                  【解决方案17】:

                  试试下面的代码

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

                  【讨论】:

                  • 你的答案和接受的答案有什么区别?我看到它在另一个答案的第一部分。
                  【解决方案18】:

                  我猜这正是你要找的东西

                      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
                  

                  【讨论】:

                    【解决方案19】:

                    流行版本不太对劲。我想你想要:

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

                    【讨论】:

                    • 如果 "foo" 出现在字符串中的任何地方,这将删除内容,而不仅仅是在开头。 "aaaaaafoofoobar" 也将返回 "foobar"
                    【解决方案20】:

                    下面的方法可以试试。

                    def remove_suffix(string1, suffix):
                        length = len(suffix)
                    
                        if string1[0:length] == suffix:
                            return string1[length:]
                        else:
                            return string1
                    
                    suffix = "hello"
                    string1 = "hello world"
                    
                    final_string = remove_suffix(string1, suffix)
                    print (final_string)
                    

                    【讨论】:

                      【解决方案21】:

                      无需编写函数,这将根据列表进行拆分,在本例中为'Mr.|Dr.|Mrs.',使用[1]选择拆分后的所有内容,然后再次拆分并获取任何元素。在下面的例子中,'Morris' 被返回。

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

                      【讨论】:

                        【解决方案22】:

                        这在技术上与其他答案非常相似,但没有重复的字符串操作,能够判断前缀是否存在,并且仍然非常可读:

                        parts = the_string.split(prefix_to_remove, 1):
                            if len(parts) == 2:
                                #  do things with parts[1]
                                pass
                        

                        【讨论】:

                        • 如果“Path=”出现在字符串中的任何地方,而不只是在开头,这将删除内容。
                        猜你喜欢
                        • 1970-01-01
                        • 1970-01-01
                        • 1970-01-01
                        • 1970-01-01
                        • 2023-02-23
                        • 1970-01-01
                        • 1970-01-01
                        • 1970-01-01
                        • 2017-07-02
                        相关资源
                        最近更新 更多