首页 > 解决方案 > 使用正则表达式读取数据

问题描述

对于我的项目,我需要读取文件并将其与我的常量匹配,一旦匹配,需要将它们存储在字典中。我将在下面展示我的数据样本以及到目前为止的数据。

我的数据:

TIMESTAMP: 1579051725 20100114-202845
.1.2.3.4.5.6.7.8.9 = 234567890
ifTb: name-nam-na
.1.3.4.1.2.1.1.1.1.1.1.128 = STRING: AA1
.1.3.4.1.2.1.1.1.1.1.1.129 = STRING: Eth1
.1.3.4.1.2.1.1.1.1.1.1.130 = STRING: Eth2

这些数据有 5 个我想收集的重要部分:

  1. 时间戳之后的日期:1579051725

  2. Num(数字的第一部分直到 128、129、130 等):.1.3.4.1.2.1.1.1.1.1.1

  3. Num2(第二部分): 128or 129or 130or others in my large data set

  4. Syntax:在这种情况下,它被命名为:STRING

  5. Counter:在这种情况下,它们是字符串;AA1Eth1Eth2

我也有(需要有)常量Num作为程序中的字典来保存上述值和常量syntax

我想通读数据文件,

  1. 如果Num与我在程序中的常量匹配,

  2. Num2

  3. 检查是否与程序Syntax中的常量匹配syntax

  4. 抓住Counter

当我说抓取时,我的意思是将数据放在相应的字典下。

简而言之,我想通读数据文件,在其中拆分 5 个变量,将 2 个变量与常量字典值匹配,并在字典下抓取并存储 3 个变量(包括时间)。

到目前为止,我在拆分数据时遇到了麻烦。我可以拆分除Numand之外的所有内容Num2。另外我不确定如何创建常量字典以及我应该如何将常量字典放在常量字典下。

我很想使用正则表达式而不是使用 if 语句,但由于数据在单词中包含许多点,因此无法弄清楚要使用哪些符号。

到目前为止,我有以下内容:

constant_dic1 = {[".1.3.4.1.2.1.1.1.1.1.1"]["STRING" ]}
data_cols = {'InterfaceNum':[],"IndexNum":[],"SyntaxName":[],"Counter":[],"TimeStamp":[]}
fileN = args.File_Name
with open (fileN, 'r') as f:

    for lines in f:
        if lines.startswith('.'):
            if ': ' in lines:
                lines=lines.split("=")
                first_part = lines[0].split()
                second_part = lines[1].split()
                for i in first_part:
                    f_f = i.split("{}.{}.{}.{}.{}.{}.{}.{}.{}.{}.{}.")
                print (f_f[0])

运行程序后,我收到“TypeError:列表索引必须是整数或切片,而不是 str”的错误。

当我注释掉字典部分时,输出NumNum2. 它不会被拆分,也不会只打印Num部分。

任何帮助表示赞赏!如果还有其他来源,请在下面告诉我。请让我知道我是否需要对该问题的任何更新,而无需投票。谢谢!

更新代码

import pandas as pd
import io
import matplotlib
matplotlib.use('TkAgg') # backend option for matplotlib #TkAgg #Qt4Agg #Qt5Agg
import matplotlib.pyplot as plt
import re # regular expression
import argparse # for optional arguments
parser = argparse.ArgumentParser()
parser.add_argument('File_Name', help="Enter the file name | At least one file is required to graph")
args=parser.parse_args()

data_cols = {'InterfaceNum':[],"IndexNum":[],"SyntaxName":[],"Counter":[],"TimeStamp":[]}
fileN = args.File_Name
input_data = fileN
expr = r"""
    TIMESTAMP:\s(\d+)           # date    - TimeStamp
    |                           # ** OR **
    ((?:\.\d+)+)                # num     - InterfaceNum
        \.(\d+)\s=\s            # num2    - IndexNum
            (\w+):\s            # syntax  - SyntaxName
                (\w+)           # counter - Counter
    """
expr = re.compile(expr, re.VERBOSE)
data = {}
keys = ['TimeStamp', 'InterfaceNum', 'IndexNum', 'SyntaxName', 'Counter']


with io.StringIO(input_data) as data_file:
    for line in data_file:
        try:
            find_data = expr.findall(line)[0]
            vals = [date, num, num2, syntax, counter] = list(find_data)
            if date:
                cur_date = date
                data[cur_date] = {k: [] for k in keys}
            elif num:
                vals[0] = cur_date
                for k, v in zip(keys, vals):
                    data[cur_date][k].append(v)
        except IndexError:
            # expr.findall(...)[0] indexes an empty list when there's no
            # match.
            pass

data_frames = [pd.DataFrame.from_dict(v) for v in data.values()]

print(data_frames[0])

我得到的错误

Traceback (most recent call last):
  File "v1.py", line 47, in <module>
    print(data_frames[0])
IndexError: list index out of range


新数据

TIMESTAMP: 1579051725 20100114-202845
.1.2.3.4.5.6.7.8.9 = 234567890
ifTb: name-nam-na
.1.3.4.1.2.1.1.1.1.1.1.128 = STRING: AA1
.1.3.4.1.2.1.1.1.1.1.1.129 = STRING: Eth1
.1.3.4.1.2.1.1.1.1.1.1.130 = STRING: Eth2
.1.2.3.4.5.6.7.8.9.10.11.131 = INT32: A

更新代码 (v2)

import pandas as pd
import io
import matplotlib
import re # regular expression

file = r"/home/rusif.eyvazli/Python_Projects/network-switch-packet-loss/s_data.txt"



def get_dev_data(file_path, timestamp=None, iface_num=None, idx_num=None, 
                 syntax=None, counter=None):

    timestamp = timestamp or r'\d+'
    iface_num = iface_num or r'(?:\.\d+)+'
    idx_num   = idx_num   or r'\d+'
    syntax    = syntax    or r'\w+'
    counter   = counter   or r'\w+'

#     expr = r"""
#         TIMESTAMP:\s({timestamp})   # date    - TimeStamp
#         |                           # ** OR **
#         ({iface_num})               # num     - InterfaceNum
#             \.({idx_num})\s=\s      # num2    - IndexNum
#                 ({syntax}):\s       # syntax  - SyntaxName
#                     ({counter})     # counter - Counter
#         """

    expr = r"TIMESTAMP:\s(\d+)|((?:\.\d+)+)\.(\d+)\s=\s(\w+):\s(\w+)"

#   expr = re.compile(expr, re.VERBOSE)

    expr = re.compile(expr)

    rows = []
    keys = ['TimeStamp', 'InterfaceNum', 'IndexNum', 'SyntaxName', 'Counter']
    cols = {k: [] for k in keys}

    with open(file_path, 'r') as data_file:
        for line in data_file:
            try:

                find_data = expr.findall(line)[0]
                vals = [tstamp, num, num2, sntx, ctr] = list(find_data)
                if tstamp:
                    cur_tstamp = tstamp
                elif num:
                    vals[0] = cur_tstamp
                    rows.append(vals)
                    for k, v in zip(keys, vals):
                         cols[k].append(v)
            except IndexError:
                # expr.findall(line)[0] indexes an empty list when no match.
                pass

    return rows, cols

const_num    = '.1.3.4.1.2.1.1.1.1.1.1'
const_syntax = 'STRING'

result_5 = get_dev_data(file)

# Use the results of the first dict retrieved to initialize the master
# dictionary.
master_dict = result_5[1]

df = pd.DataFrame.from_dict(master_dict)

df = df.loc[(df['InterfaceNum'] == '.1.2.3.4.5.6.7.8.9.10.11') & (df['SyntaxName'] == 'INT32' )] 

print(f"\n{df}")

输出

    TimeStamp              InterfaceNum IndexNum SyntaxName Counter
3  1579051725  .1.2.3.4.5.6.7.8.9.10.11      131      INT32       A

标签: pythonregexpython-3.xpandasread-data

解决方案


请使用 python "re" 包在 python 中使用正则表达式。这个包使得在 python 中使用正则表达式变得非常容易,你可以使用这个包中的各种函数来实现你所需要的。https://docs.python.org/3/library/re.html#module-contents使用此链接阅读文档。

有一个名为 re.Pattern.match() 的函数可用于匹配模式,因为您需要尝试一下。


推荐阅读