使用正则表达式检查值的文本文件是否遵循约定

2024-06-06 04:08:39 发布

您现在位置:Python中文网/ 问答频道 /正文

大家好

我正在编写一个python脚本来解析正好包含两列整数(空格或制表符分隔)的文本文件,类似于以下示例:

3141 5926
535 89
79 32

11 2
1 4

如果一个文件不遵循这个约定(例如一行中有1个或3个或更多的值,字母…),我希望能够从一开始就拒绝它

到目前为止,我想出了 ^\d+[ \t]+\d+$ 这可以说是不多的(我尝试了不同的方法,但没有用,不幸的是,我对regex不太熟悉)。我正在考虑编写一个表达式,如果文件不符合约定,它要么返回匹配项,要么不返回

我的问题是:

  1. 正则表达式是正确的工具还是读取文件和处理字符串的传统方法更好
  2. 我该怎么办?我的方法到底值不值得
  3. 有没有一种方法不仅可以匹配整个文本文件,还可以提取最后一段

我正在使用re开发python3

任何指点都很感激


Tags: 文件工具方法字符串re脚本示例表达式
2条回答

您可以使用pandas将文本文件加载到带有^{}的数据帧中,然后检查所有值是否为整数,以及2中的列数是否为:

import pandas as pd
from glob import glob

files = glob('/path/to/files/*.txt') #get a list of all txt files

for i in files:
    df = pd.read_csv(i, sep=' |\t', engine='python', header=None) #sep=' |\t' will process both space- and tab-delimited files
    if (df.dtypes == 'int64').all() and len(df.columns) == 2: #check if all values are integers and if the number of columns is 2
        #do something here

如何仅读取最后一段取决于文件的结构,如果第二段始终是第四行,您可以使用df[3:]访问它。如果没有模式,您可以这样提取第二段:

with open('filename.txt') as file:
    data = [[int(x) for x in i.strip().split()] for i in file.readlines()] #create list of lists of items in rows
    data = data[data.index([])+1:] #slice list after the empty row

我设法做到了我最初打算做的事情

我使用了以下模式:

\n*(?:(?:[ \t]*\d+[ \t]+\d+[ \t]*\n)*(?:[ \t]*\d+[ \t]+\d+[ \t]*)\n\n)*(?P<last>(?:[ \t]*\d+[ \t]+\d+[ \t]*\n)*(?:[ \t]*\d+[ \t]+\d+[ \t\n]*))

它匹配包含由空格或制表符分隔的整数对(每行一对)的文本。该模式还允许成对组之间有一条白线(如我的示例中所示)。它还捕获名为last的组中的最后一组对

现在,这将匹配一个部分兼容的文件,这是我不想要的。诀窍是使用re.fullmatch()而不是re.match()。如果只有部分匹配,则此方法返回None

上述模式执行以下操作:

  • \n*与前导换行符匹配
  • (?:(?:[ \t]*\d+[ \t]+\d+[ \t]*\n)*(?:[ \t]*\d+[ \t]+\d+[ \t]*)\n\n)*与除最后一组对之外的所有对匹配(因此末尾的*):
    • (?:[ \t]*\d+[ \t]+\d+[ \t]*\n)*使用单行对或整数在0到无限次之间进行匹配,允许前导和尾随空格/制表符
    • (?:[ \t]*\d+[ \t]+\d+[ \t]*)\n\n与一组对的最后一行正好匹配一次。这实际上是上述重复模式的基本情况
  • (?P<last>(?:[ \t]*\d+[ \t]+\d+[ \t]*\n)*(?:[ \t]*\d+[ \t]+\d+[ \t]*))遵循上面讨论的相同原理,将其作为最后一个重复非捕获组的基本情况。它允许无限量的尾随行
  • \n*与尾部换行符匹配

相关问题 更多 >