【问题标题】:python find digits string in linepython在行中查找数字字符串
【发布时间】:2020-10-13 20:20:38
【问题描述】:

我有这种长日志文件。

2012-02-03 18:35:34 SampleClass6 [INFO] everything normal for id 174025851
2012-02-03 18:35:34 SampleClass4 [FATAL] system problem at id 1991740254
2012-02-03 18:35:34 SampleClass3 [DEBUG] detail for id 1304807656
2012-02-03 18:35:34 SampleClass3 [WARN] missing id 1740

我想准确地找到id=1740,并打印行,但id=174025851 也算在内。如何在一行中找到准确的字符串id=1740 并打印行。

for line in f: 
    if str(id) in line: 
        print(line)

它还打印第一行和第二行,但我只想要第 4 行,只有 id 1740

【问题讨论】:

  • 如果你的意思是 完全 那么 line.strip().endsWith(“id 1740”) 或类似的东西? (不在一台机器上测试这个自动取款机。)
  • 如果您使用re 模块,那么re.search(r'\b1740\b',line) 不够用吗?
  • Zaman Azam:我更新了我的答案,以反映你在 pciunkiewicz 的回答下写的关于“id”可能出现在字符串的 middle 以及结尾。这个细节应该在问题的前面说明,因为不知道它会使许多答案无效。请您现在编辑您的问题以反映要求。

标签: python regex string match digits


【解决方案1】:

冒着为已经有很多问题添加另一个答案的风险,我认为这里最好使用正则表达式解析器:

import re

the_id = 1740

with open("test.txt") as f:
    for line in f:
        match = re.search("id\s+(\d+)\s*$", line)
        if match and the_id == int(match.group(1)):
            print(line, end='')

这给出了:

2012-02-03 18:35:34 SampleClass3 [WARN] missing id 1740

您在这里所做的是使用解析器查找以下结尾的行:“id”,后跟空格,后跟一个或多个数字(您在一个组中捕获),可选地后跟任意数量的空白。

然后将捕获的组转换为 int 并与 id 进行比较。

顺便说一句,id 存储在名为the_id 的变量中,因为id 是内置函数的名称,因此不是一个好的变量名称选择(影响内置函数的使用)。


更新

提问者现已澄清,ID 可以出现在行的中间,不一定出现在行尾。

这可以通过对正则表达式的简单调整来轻松处理。将上述代码中的相关行改为:

        match = re.search("id\s+(\d+)", line)

现在取消对数字后的任何检查。

因为+ 的意思是“一个或多个”也是贪婪(也就是说,它尽可能多地匹配与其相关的模式部分),ID 的整个由括号组匹配,不需要指定任何关于它后面的内容。

给定输入文件

2012-02-03 18:35:34 SampleClass6 [INFO] everything normal for id 174025851
2012-02-03 18:35:34 SampleClass4 [FATAL] system problem at id 1991740254
2012-02-03 18:35:34 SampleClass3 [DEBUG] detail for id 1304807656
2012-02-03 18:35:34 SampleClass3 [WARN] missing id 1740
2012-02-03 19:11:02 id 1740 SampleClass5 [TRACE] verbose detail

现在将输出:

2012-02-03 18:35:34 SampleClass3 [WARN] missing id 1740
2012-02-03 19:11:02 id 1740 SampleClass5 [TRACE] verbose detail

【讨论】:

  • 这条线也用这个吗
  • 2 月 23 日 07:38:19 router1 snmpd[359]:SNMPD_TRAP_COLD_START:trap_generate_cold:SNMP 1740 陷阱:冷启动
  • @ZamanAzam 这甚至不包含字符串id。代码应该如何知道这是一个 id?
  • 所以我有不同的日志文件。我使用 .log 过滤。然后我读了第一个文件。并且文件中的每一行都包含不同的数字字符串。数字(Id)由用户给出。如果它在行中完全相同。然后打印行
  • snmpd[359]: SNMPD_TRAP_WARM_START:SNMP 陷阱:热启动 SNMPD_THROTTLE_QUEUE_DRAINED:() 清除了所有受限制的陷阱 SNMPD_TRAP_WARM_START:SNMP 陷阱:(1740;543;544) 热启动 SNMPD_TRAP_COLD_START:SNMP 陷阱:(1740737)冷启动
【解决方案2】:

您可以使用正则表达式,例如 id 后跟空格。 或者如果 id 总是在行尾。然后使用 如果 line.endswith('id '+id) 是真的,那么按照你的逻辑。

【讨论】:

    【解决方案3】:

    你可以使用正则表达式

    import re
    text = """
    2012-02-03 18:35:34 SampleClass6 [INFO] everything normal for id 174025851
    2012-02-03 18:35:34 SampleClass4 [FATAL] system problem at id 1991740254
    2012-02-03 18:35:34 SampleClass3 [DEBUG] detail for id 1304807656
    2012-02-03 18:35:34 SampleClass3 [WARN] missing id 1740
    """
    
    # the \s means the char after 0 must be a space, tab or newline (so, not a number)
    p = re.compile(r'.*id 1740\s') 
    ls = p.findall(text)
    

    【讨论】:

      【解决方案4】:

      这是另一种可能性:

      import pandas as pd
      
      data=pd.read_csv('/path/to/data.txt', header=None)
      
      for i in range(0,len(data)):
          if data.iloc[i,0].split(' ')[-1][:4]=='1740':
              print(data.iloc[i,0])
      

      即使没有逗号分隔,我也会使用 csv,以便将行保留为单个字符串!然后在循环内检查。

      【讨论】:

        【解决方案5】:

        您可以这样做并拆分行并取最后一个值:

        for line in f: 
            if '1740' in line:
                a = line.split(' ')[-1]
                if a == '1740': 
                    print(line)
        

        【讨论】:

        • 我认为不希望您对值 '1740' 进行硬编码(尤其是在两个地方没有硬编码相同的常量),但您可能想借此机会建议一个比问题中使用的 id 更好的变量名(这是内置函数的名称)。
        【解决方案6】:

        根据您的日志结构,如果 id 始终位于行尾,您可以随时更改它以查找以您的确切查询结尾的行:

        for line in f: 
            if line.endswith(f"id {id}"): 
                print(line)
        

        编辑:

        正如@mrblewog 所提到的,如果行有尾随空格,我们可以使用rstripstrip 对其进行预处理:

        for line in f:
            line = line.rstrip()
            ### Rest of the logic ###
        

        【讨论】:

        • 可能需要在 endwith 之前从行中去除空格
        • 如果要搜索的行 id 是 1740 但行以 1991740 结尾怎么办?这行不通。
        • @DavidErickson 啊,是的,你是对的!我已将其更新为更精确,从id XXXXXXXX 开始。
        • id也可以出现在中间,是一个长日志文件
        • 2012-02-03 19:11:02 id 1740 SampleClass5 [TRACE] 详细信息
        【解决方案7】:

        你可以用正则表达式来做 -

        import re
        file = ['2012-02-03 18:35:34 SampleClass6 [INFO] everything normal for id 174025851',
        '2012-02-03 18:35:34 SampleClass4 [FATAL] system problem at id 1991740254',
        '2012-02-03 18:35:34 SampleClass3 [DEBUG] detail for id 1304807656',
        '2012-02-03 18:35:34 SampleClass3 [WARN] missing id 1740']
        for line in file :
            num = re.findall(r'\d+', line)[-1]
            if(num == '1740'):
                print(line)
        

        输出:

        2012-02-03 18:35:34 SampleClass3 [WARN] missing id 1740
        

        使用此代码,即使字符串不是以数字结尾,您也会找到每行出现的最后一个数字。


        以下将检查1740 是否出现在行中的任何位置。

        import re
        file = ['2012-02-03 18:35:34 SampleClass6 [INFO] everything normal for id 174025851',
        '2012-02-03 18:35:34 SampleClass4 [FATAL] system problem at id 1991740254',
        '2012-02-03 18:35:34 SampleClass3 [DEBUG] detail for id 1304807656',
        '2012-02-03 18:35:34 SampleClass3 [WARN] missing id 1740',
        '2012-02-03 19:11:02 id 1740 SampleClass5 [TRACE] verbose detail ']
        for line in file :
            num = re.findall(r'\d+', line)
            if('1740' in num):
                print(line)
        

        或者,如果您确定每行都以数字结尾,那么您可以简单地拆分字符串并与拆分的最后一个元素进行比较 -

        file = ['2012-02-03 18:35:34 SampleClass6 [INFO] everything normal for id 174025851',
        '2012-02-03 18:35:34 SampleClass4 [FATAL] system problem at id 1991740254',
        '2012-02-03 18:35:34 SampleClass3 [DEBUG] detail for id 1304807656',
        '2012-02-03 18:35:34 SampleClass3 [WARN] missing id 1740']
        
        for line in file :
            num = line.split()[-1]
            if(num == '1740'):
                print(line)
        

        输出:

        2012-02-03 18:35:34 SampleClass3 [WARN] missing id 1740
        

        【讨论】:

        • id 可以在文件中的任何位置。就像在弦线中间一样。
        • 那么正则表达式代码将为您工作(只要它出现在该行的最后一个数字)
        • like id在文件中可以这样出现,
        • 2012-02-03 19:11:02 id 1740 SampleClass5 [TRACE] 详细信息
        • @ZamanAzam 看看我现在添加的第二个是否有帮助。它适用于您提供的案例
        猜你喜欢
        • 2023-04-06
        • 1970-01-01
        • 2017-04-18
        • 2021-08-13
        • 1970-01-01
        • 2014-07-10
        • 2016-10-02
        • 2023-04-03
        • 1970-01-01
        相关资源
        最近更新 更多