【问题标题】:Search same string in line of file在文件行中搜索相同的字符串
【发布时间】:2021-03-14 16:58:21
【问题描述】:

在一个文件中,我有几行具有这种结构:

> Present one time: "Instance: ...Edition: ..."
> Present two times: "Instance: ...Edition: ...Instance: ...Edition: ..."
> Present n times: "Instance: ...Edition: ... [n] Instance: ...Edition: ..."

这种结构可以每行出现一次,也可以在同一行出现多次。思路是逐行读取文件,隔离所代表的值... em> 并将它们写入一个 excel 文件。我可以做到,但如果上面的结构在一行中出现一次,我只能隔离这些值。如果该结构在行上存在不止一次,我只能保存第一个结构的值。 这是我的代码:

#READ FILE
for i in fin:
    if "Instance:" in i:
        instance = ((i.split('Instance:'))[1].split('Edition')[0])
        worksheet.write(row, col, instance)
    if "Edition:" in i:
        edition = ((i.split('Edition:'))[1].split('\n')[0])
        worksheet.write(row, col, edition)
    row += 1

知道如何解决这个问题吗?

【问题讨论】:

  • 所以你想从字符串中删除每个“Instance”、“Edition:”和“\n”,然后将剩余的内容串联起来?
  • 另外,如果“Instance”和“Edition”都存在,那么“Edition”后面的内容会覆盖“Instance”后面的内容,这是你想要的吗?
  • 那些不以“Instance”开头但包含“Edition”的行怎么办......这可能吗?现在你的代码允许它。
  • 这个想法是,如果行看起来像这样:“实例:1 版本:2 实例:3 版本:4”,我可以隔离 1、2、3、4,但现在用我的代码我只能隔离1和2。希望清楚

标签: python string file substring


【解决方案1】:

请注意,这仅在您的输入以空行(称为换行符)结尾时才有效。 如果没有,您可以像这样添加它:s += '\n'

s = '''Instance: A Edition: Limited
Instance: B Edition: Common Instance: C Edition: 2020 Instance: D Edition: Bla
'''

result = []
start_in = start_ed = None
for i in range(len(s)):
    # Reaching the end of a data item
    if s[i:i+9] == 'Instance:' or s[i] == '\n':
        if start_in and start_ed:
            result.append(
                (s[start_in:start_ed-8].strip(), s[start_ed:i].strip())
            )
            start_in = start_ed = None

    if s[i:i+9] == 'Instance:':
        start_in = i+9
    if s[i:i+8] == 'Edition:':
        start_ed = i+8

print(result)
[('A', 'Limited'), ('B', 'Common'), ('C', '2020'), ('D', 'Bla')]

编辑:根据要求使用Version 字段

s = '''Instance: A Edition: Limited Version: 1
Instance: B Edition: Common Version: 2 Instance: C Edition: 2020 Version: 3 Instance: D Edition: Bla Version: 4
'''

result = []
start_in = start_ed = start_vs = None
for i in range(len(s)):
    # Reaching the end of a data item
    if s[i:i+9] == 'Instance:' or s[i] == '\n':
        if start_in and start_ed and start_vs:
            result.append((
                s[start_in:start_ed-8].strip(),
                s[start_ed:start_vs-8].strip(),
                s[start_vs:i].strip()
            ))
            start_in = start_ed = start_vs = None

    if s[i:i+9] == 'Instance:':
        start_in = i+9
    if s[i:i+8] == 'Edition:':
        start_ed = i+8
    if s[i:i+8] == 'Version:':
        start_vs = i+8

print(result)

【讨论】:

  • 非常感谢!我更喜欢这个解决方案,因为它更容易理解。现在如果结构在 Edition 之后有一个 Version 字段,是否会在代码末尾添加 s[i:i+9] == 'Version:' ?
  • 版本字段是始终存在还是可选的?您将需要一个额外的变量 start_vs 并且由于字符串“版本:”有 8 个字母,它将是 s[i:i+8] == 'Version:' 并附加 s[start_ed:start_vs-8]s[start_vs:i]
  • 非常感谢您的帮助,我会做测试,您帮了我很多!万事如意
  • 很高兴我能帮上忙
  • 如果结构变为“实例:...版本:...版本:...”,我没有得到结果,请您帮帮我
【解决方案2】:

使用regular expression 的替代解决方案。这更短,但可能更难阅读和维护:

import re
r = re.findall(r'Instance:([\w|\s]+?)Edition:([\w|\s]+?)(?=Instance|\n)', s)
[(' A ', ' Limited'), (' B ', ' Common '), (' C ', ' 2020 '), (' D ', ' Bla')]

如果您不希望匹配项周围有空格,您可以像我在其他解决方案中所做的那样将strip 应用于所有元素,或者您可以修改正则表达式以读取Instance: ([\w...

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-09-06
    • 1970-01-01
    • 2019-10-24
    • 1970-01-01
    • 2018-07-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多