【问题标题】:Extract line from txt file using python使用python从txt文件中提取行
【发布时间】:2021-01-20 16:14:27
【问题描述】:

我是新来的,目前正在学习 python。这是我在这里的第一篇文章。

我正在尝试提取特定用户通过 .txt 文件发送的聊天记录。例如号码 +99 9999 9999。但我无法获取两者之间的内容。

02/09/2020, 23:45 - +99 9999 9999: 02/09/2020
task A -Changes A
task b Changes b
03/09/2020, 01:55 - +88 8888 8888: 2-SEP-2020
task c -Changes c
task d Changes d
03/09/2020, 01:55 - +99 9999 9999: 2-SEP-2020
task e -Changes e
task f Changes f

我当前的代码是

number = "+99 9999 9999"
with open('text.txt') as input_data:
    for line in input_data:
        if number in line: 
            print(line)

我的输出是包含内容的数字

02/09/2020, 23:45 - +99 9999 9999: 02/09/2020
03/09/2020, 01:55 - +99 9999 9999: 2-SEP-2020

如果数字与行匹配,我如何编辑代码以显示后面的行?任何指导将不胜感激。

我想要的输出

02/09/2020, 23:45 - +99 9999 9999: 02/09/2020
task A -Changes A
task b Changes b
03/09/2020, 01:55 - +99 9999 9999: 2-SEP-2020
task e -Changes e
task f Changes f

新数据

[23/9/20, 11:26:42 PM] John - Salesman: 23/09/2020
-task a
-task b
[23/9/20, 11:30:03 PM] Shawn - Support: 23/09/2020
-task c
-task d
[24/9/20, 9:54:44 PM]Shawn - Support: 24/09/2020
-task e
-task f
[24/9/20, 10:06:58 PM] Damien - Support: 24/09/2020
-task g
-task h
-task i
-task j
[24/9/20, 10:53:52 PM] John - Salesman: 24/09/2020
-task k
-task l
-task m
-task n

【问题讨论】:

    标签: python


    【解决方案1】:

    您已整理好文件读取部分。你需要弄清楚打印语句。

    这是处理它的代码。为简单起见,我将文件中的所有数据分配给一个变量。我还修改了输入数据。第一组有 3 行表示 +99 9999 9999

    import re
    
    filedata = '''02/09/2020, 23:45 - +99 9999 9999: 02/09/2020
    task A -Changes A
    task b Changes b
    task c Changes c
    03/09/2020, 01:55 - +88 8888 8888: 2-SEP-2020
    task c -Changes c
    task d Changes d
    03/09/2020, 01:55 - +99 9999 9999: 2-SEP-2020
    task e -Changes e
    task f Changes f'''
    
    number = '+99 9999 9999'
    
    for line in filedata.split('\n'):
        z = re.match(r"[+\d{2} \d{4} \d{4}]",line)
        if z: found = number in line
        if found: print (line)
    

    上面代码的解释:

    对于读取的每一行,对 +nn nnnn nnnn 进行正则表达式匹配,其中 n 是任意数字(d 表示数字)。结果被发送到z。

    如果 z 有任何值,则找到匹配项。如果我们找到匹配项,那么您想知道该行是 +99 9999 9999 还是其他数字模式。

    如果模式匹配,则将标志设置为 found。 如果找到标志,则打印该行。 继续打印该行,直到找到下一组 +nn nnnn nnnn 行。找到后,检查是否为+99 9999 9999。如果不是,则将标志设置为False。条件found = number in line 的结果为真或假。当标志为 False 时,我们知道已经开始了不同的集合。停止打印线条。

    希望这可以解释。如果您对逻辑仍有疑问,请告诉我。

    这个输出将是:

    02/09/2020, 23:45 - +99 9999 9999: 02/09/2020
    task A -Changes A
    task b Changes b
    task c Changes c
    03/09/2020, 01:55 - +99 9999 9999: 2-SEP-2020
    task e -Changes e
    task f Changes f
    

    无论您在 +99 9999 9999 和下一组 +nn nnnn nnnn 之间有多少行,这都会起作用,其中 n 可以是任何数字。

    这是读取文件所需的代码:

    import re
    number = "+99 9999 9999"
    with open('text.txt') as input_data:
        for line in input_data:
            z = re.match(r"[+\d{2} \d{4} \d{4}]",line)
            if z: found = number in line
            if found: print (line)
    

    我正在对您在这里尝试做的事情进行一些疯狂的猜测。

    假设您想在文件中找到John +99 9999 9999 作为字符串并打印与此相关的所有行。然后是代码。

    import re
    filedata = '''02/09/2020, 23:45 - John +99 9999 9999: 02/09/2020
    task A -Changes A
    task b Changes b
    task c Changes c
    03/09/2020, 01:55 - Suzan +88 8888 8888: 2-SEP-2020
    task c -Changes c
    task d Changes d
    03/09/2020, 01:55 - Thomas +99 9999 9999: 2-SEP-2020
    task e -Changes e
    task f Changes f'''
    
    name = 'John'
    for line in filedata.split('\n'):
        z = re.findall(r"\w+ \+\d{2} \d{4} \d{4}",line)
        if z: found = (name in line) and (line[:4] != 'task')
        if found: print (line)
    

    这个输出将是:

    02/09/2020, 23:45 - John +99 9999 9999: 02/09/2020
    task A -Changes A
    task b Changes b
    task c Changes c
    

    这适用于以下代码模式:

    02/09/2020, 23:45 - John , Salesman +99 9999 9999: 02/09/2020
    
    02/09/2020, 23:45 - John Salesman +99 9999 9999: 02/09/2020
    

    让我知道您要查找的内容。希望所有这些示例都能帮助您获得所需的内容。

    根据您分享的新数据,代码如下:

    filedata = """[23/9/20, 11:26:42 PM] John - Salesman: 23/09/2020
    -task a
    -task b
    [23/9/20, 11:30:03 PM] Shawn - Support: 23/09/2020
    -task c
    -task d
    [24/9/20, 9:54:44 PM]Shawn - Support: 24/09/2020
    -task e
    -task f
    [24/9/20, 10:06:58 PM] Damien - Support: 24/09/2020
    -task g
    -task h
    -task i
    -task j
    [24/9/20, 10:53:52 PM] John - Salesman: 24/09/2020
    -task k
    -task l
    -task m
    -task n"""
    
    import re
    name = 'John - Salesman'
    for line in filedata.split('\n'):
        z = re.findall(r"([\w+ \- \w+:]*\d{2}\/\d{2}\/\d{4})",line)
        if z: found = (name in line) and (line[:4] != 'task')
        if found: print (line)
    

    这个输出将是:

    [23/9/20, 11:26:42 PM] John - Salesman: 23/09/2020
    -task a
    -task b
    [24/9/20, 10:53:52 PM] John - Salesman: 24/09/2020
    -task k
    -task l
    -task m
    -task n
    

    如果你想玩弄正则表达式,你可以在这里试试regEx expression

    【讨论】:

    • 非常好!作为建议,您可以在您的正则表达式中使用 ?P<number> 并且只检查 z['number'] == number 而不是再次搜索整行。
    • 太棒了,谢谢!如果不是按数字搜索,而是按名称搜索,该怎么办。我知道搜索条件现在不同了。我尝试用 \w 替换 \d 但我得到的输出只是带有名称的行。
    • 名称可以是不同的长度。您需要提供 \w+ 才能获得全名。 >>> m = re.match(r"(\w+) (\w+)", "Isaac Newton, physicist") >>> m[0] # 整个匹配 'Isaac Newton' >>> m[1] # 第一个带括号的子组。 'Isaac' >>> m[2] # 第二个带括号的子组。 '牛顿'
    • 如果这个回答,别忘了标记为回答
    • 我尝试使用 >>> z = re.match(r"[(\w+) (\W) (\w+)]", "john, -, salesman") 来查找但似乎就像唯一的回报是第一行。你认为我需要有一个条件让它先检查日期然后找到名字直到下一个日期吗?
    【解决方案2】:

    这是你的答案:

    number = "+99 9999 9999"
    with open('text.txt') as input_data:
        lines = input_data.readlines()
    
        # Instead of looping over the lines, we
        # loop over an array of integers starting
        # from zero and ending at the (number of
        # lines in the file minus 1).
        # (Remember,python lists are zero indexed, thats why)
        for line_no in range(len(lines)):
            if number in lines[line_no]:
    
                # The current line
                print(lines[line_no], end="")
    
                # Print the next line
                print(lines[line_no+1], end="")
    
                # And the next one too
                print(lines[line_no+2], end="")
    

    【讨论】:

    • 如果我有超过 2 行或者说中间的内容是随机的,可能是 2 行可能是 5 甚至 10 行。我该怎么做?我应该在 if 之后添加另一个 for 循环吗?
    • 你确定这会起作用吗? line_no 将在到达 for 循环时重置为 next no。此外,这是假设 +99 9999 9999 行之后总是有 2 行
    • @Fuji 使用re 是要走的路。您可以使用它从消息中提取更多信息(您在其他答案上的 cmets 建议您这样做)。不过,我的建议是使用其他格式,例如 json 来存储该数据(如果您控制它)。
    • @JoeFerndz 你是对的,我把那部分弄错了。感谢您指出。
    【解决方案3】:

    因为你的代码只是找到包含你想要的数字的行,你可以设置一个标志来打印以下内容直到另一个数字:

    if __name__ == '__main__':
        number = "+99 9999 9999"
        task = 'task'
        wanted = False
        with open('text.txt') as input_data:
            for line in input_data:
                if number in line or wanted:
                    wanted = True
                    print(line.strip())
                if line[:4] != task and number not in line:
                    wanted = False
    
    

    【讨论】:

      【解决方案4】:
      import re
      
      with open('text.txt') as input_data:
          lines = input_data.readlines()
          re_number = re.compile("\+\d\d \d\d\d\d \d\d\d\d")
          number = "+99 9999 9999"
          blocks = []
          tmp_block = []
          for index, line in enumerate(lines):
              if (re_number.search(line)):
                  if (tmp_block):
                      blocks.append(tmp_block.copy())
                      tmp_block.clear()
                      flag = 0
                  if (number in line):
                      flag = 1
              if (flag):
                  tmp_block.append(line)
          if (flag):
              blocks.append(tmp_block.copy())
      
      print (blocks)
      

      【讨论】:

      • 你可以给出 \d{n} 其中 n 是你想要的次数 \d
      【解决方案5】:

      任务 1

      如果您的历史文件有超过 2 个针对单个电话号码的任务,这将是我的另一个解决方案。

      代码语法

      inp = input("please, Enter your input that you want to search for: ")
      
      
      def scanner (path, input):
          with open(path) as file:
               lines = file.readlines()
               for index, line in enumerate(lines):
                   if line[0].isdigit() == True and line[20: -13] == input:
                       print(line)
                       lin = index+1
                       try:
                           while lines[lin][0].isdigit() is False:
                               print(lines[lin])
                               lin +=1
                       except IndexError:
                           break
      
      print("="*40)
      print(f"*****History of {inp}*****")        
      scanner(path, inp)
      

      输出

      please, Enter your input that you want to search for: +99 9999 9999
      ========================================
      *****History of +99 9999 9999*****
      02/09/2020, 23:45 - +99 9999 9999: 02/09/2020
      
      task A -Changes A
      
      task b Changes b
      
      03/09/2020, 01:55 - +99 9999 9999: 2-SEP-2020
      
      task e -Changes e
      
      task f Changes f
      
      [Program finished]
      

      任务 2

      这个和同一个点有那么大的关系,这里的区别在于提取的搜索操作。

      代码语法

      def scanner2(path, input):
          with open(path) as file:
               lines = file.readlines()
               for index, line in enumerate(lines):
                   if line[1].isdigit() == True and line[22: -13].strip(" ") == input:
                       print(line)
                       lin = index+1
                       try:
                           while lines[lin][1].isdigit() is False:
                               print(lines[lin])
                               lin +=1
                       except IndexError:
                           break
      
      
      print("="*40)
      print(f"*****History of {inp}*****")        
      scanner2(path2, inp)
      

      输出输入区分大小写

      please, Enter your input that you want to search for: John - Salesman
      ========================================
      *****History of John - Salesman*****
      [23/9/20, 11:26:42 PM] John - Salesman: 23/09/2020
      
      -task a
      
      -task b
      
      [24/9/20, 10:53:52 PM] John - Salesman: 24/09/2020
      
      -task k
      
      -task l
      
      -task m
      
      -task n
      
      [Program finished]
      

      【讨论】:

        【解决方案6】:

        试试这个代码,

        代码语法

        path = 'extractiondata.txt'
        
        def scanner(path, input):
            with open(path) as file:
                lista  = file.readlines()
                for index, each in enumerate(lista):
                    if each[20:-13] == input:
                        print(each)
                        print(lista[index+1])
                        print(lista[index+2])                
                
        
        inp = input("please, Enter your input that you want to search for: ")                  
        scanner(path, inp)
        
        
        

        输出

        02/09/2020, 23:45 - +99 9999 9999: 02/09/2020
        
        task A -Changes A
        
        task b Changes b
        
        03/09/2020, 01:55 - +99 9999 9999: 2-SEP-2020
        
        task e -Changes e
        
        task f Changes f
        

        【讨论】:

        • 这不是 OP 想要的。您必须在找到数字后打印行,直到找到不匹配的数字!
        • 我还在努力。我只是想与您分享这个特别的答案,以了解它的大局!
        • @StefanKssmr 我希望这是你想要的!
        【解决方案7】:

        只需检查您想要的号码是否在字符串中

        with open('text.txt') as input_data:
          lines = [i.rstrip('\n') for i in input_data.readlines()]
        
        blocks = []
        number = "+99 9999 9999"
        while len(lines) != 0:
          if number in lines[0]:
            blocks.append(lines[:3])
          lines = lines[3:]
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2013-06-23
          • 1970-01-01
          • 1970-01-01
          • 2022-06-30
          • 1970-01-01
          • 2019-05-05
          • 2021-09-25
          • 1970-01-01
          相关资源
          最近更新 更多