【问题标题】:How to print portion of the string from 'startswith' till 'endswith'如何打印从'startswith'到'endswith'的部分字符串
【发布时间】:2019-04-05 23:11:37
【问题描述】:

我喜欢将原始文本文件的部分内容(可以在“startswith”和“endswith”字符串之间进行识别)保存到一个新的文本文件中。

示例:输入文本文件包含以下行:

...abc…
...starts with string...
...def...
...ends with string...
...ghi...

...jkl...
...starts with string...
...mno...
...ends with string...
...pqr...

我有兴趣将以下行提取到输出文本文件中:

starts with string...def...ends with string
starts with string...mno...ends with string

我的以下代码返回空列表 [ ]。请帮助更正我的代码。

with open('file_in.txt','r') as fi:
    id = []
    for ln in fi:
        if ln.startswith("start with string"):
            if ln.endswith("ends with string"):
                id.append(ln[:])
                with open(file_out.txt, 'a', encoding='utf-8') as fo:
                    fo.write (",".join(id))
print(id)

我希望 file.out.txt 包含所有以“以字符串开头”并以“以字符串结尾”结尾的字符串。

【问题讨论】:

  • 感谢更新测试数据。我已经相应地更新了my answer,请检查它是否符合您的需求。

标签: python python-3.x startswith ends-with


【解决方案1】:

在每一行的末尾都有一个字符告诉计算机显示一个新行。我在这里假设“以字符串开头”和“以字符串结尾”在同一行。如果不是这种情况,请在第一个 if 语句的正下方添加 --"id.append(ln[:])"--。

试试

ln.endswith("ends with string"+'\n' )

ln.endswith("ends with string"+'\n' +'\r')
with open('C:\\Py\\testing.txt','r') as fi:
    id = []
    x = 0
    copy_line = False
    for ln in fi:
        if "starts with string" in ln:
            copy_line = True
        if copy_line:
            id.append ( ln[:] )
        if "ends with string" in ln :
            copy_line = False

    with open ('C:\\Py\\testing_out.txt', 'a', encoding='utf-8' ) as fo:
        fo.write (",".join(id))

print(id)

【讨论】:

  • 仍然返回空列表 [ ]。我会尝试一些变化的更新。谢谢。
  • 我有另一个使用布尔运算符的策略。查看更新的代码。
【解决方案2】:

startswithendswith 返回 True 或 False,而不是您可以用来分割字符串的位置。请改用findindex。例如:

start = 'starts with string'
end = 'ends with string'
s = '...abc… ...starts with string... ...def... ...ends with string... ...ghi...'

sub = s[s.find(start):s.find(end) + len(end)]
print(sub)
# starts with string... ...def... ...ends with string

您需要在循环中添加一些检查以查看开始和结束字符串是否存在,因为如果不匹配,find 将返回 -1,这会导致一些意外的切片。

【讨论】:

    【解决方案3】:

    您可以使用单独的变量来指示当前行是否是感兴趣部分的一部分,并根据开始和停止标记切换此变量。然后你也可以把这个函数变成一个生成器:

    def extract(fh, start, stop):
        sub = False
        for line in fh:
            sub |= start in line
            if sub:
                yield line
                sub ^= stop in line
    
    with open('test.txt') as fh:
        print(''.join(extract(fh, 'starts with string', 'ends with string')))
    

    在 Python 3.8 中你可以使用assignment expressions:

    import itertools as it
    
    def extract(fh, start, stop):
        while any(start in (line := x) for x in fh):
            yield line
            yield from it.takewhile(lambda x: stop not in x, ((line := y) for y in fh))
            yield line
    
    with open('test.txt') as fh:
        print(''.join(extract(fh, 'starts with string', 'ends with string')))
    

    变化:不包括开始和停止标记

    如果要从输出中排除开始和停止标记,我们可以再次使用itertools.takewhile

    import itertools as it
    
    def extract(fh, start, stop):
        while any(start in x for x in fh):
            yield from it.takewhile(lambda x: stop not in x, fh)
    
    with open('test.txt') as fh:
        print(''.join(extract(fh, 'starts with string', 'ends with string')))
    

    【讨论】:

    • @MadPhysicist 我已经更新了我的答案以满足 OP 的要求(在输出中包括开始和停止标记),还提供了一个示例用法。
    • @a_guest:使用“赋值表达式”:以下错误:>文件“”,第 4 行 while any(start in (line := x) for x in fh): ^ SyntaxError: 无效语法
    • @anatta 如前所述,赋值表达式是在 Python 3.8 中引入的,目前仅作为 alpha version 提供。
    • @a_guest:错过了。我将更新到 3.8 alpha,并尝试。谢谢。
    猜你喜欢
    • 1970-01-01
    • 2021-04-28
    • 1970-01-01
    • 1970-01-01
    • 2021-12-23
    • 1970-01-01
    • 2014-08-05
    • 1970-01-01
    相关资源
    最近更新 更多