Python 如何编写正则表达式以匹配以空格分隔的多行列数据
所以我有以Python 如何编写正则表达式以匹配以空格分隔的多行列数据,python,regex,parsing,text,Python,Regex,Parsing,Text,所以我有以 n400_108tb_48gb 2 G 1,3-7 1 20G / 286T (< 1% ) n400_108tb_48gb:1 1 D 1-3:bay1-6 - 2.1G / 48T (< 1% ) n400_108tb_48gb:3 3 D 1-3:bay7-12 - 1.9G
n400_108tb_48gb 2 G 1,3-7 1 20G / 286T (< 1% )
n400_108tb_48gb:1 1 D 1-3:bay1-6 - 2.1G / 48T (< 1% )
n400_108tb_48gb:3 3 D 1-3:bay7-12 - 1.9G / 48T (< 1% )
n400_108tb_48gb:4 4 D 1-3:bay13-18 - 10G / 48T (< 1% )
n400_108tb_48gb:5 5 D 1-3:bay19-24 - 2.0G / 48T (< 1% )
n400_108tb_48gb:6 6 D 1-3:bay25-30 - 2.2G / 48T (< 1% )
n400_108tb_48gb:7 7 D 1-3:bay31-36 - 1.7G / 48T (< 1% )
我是说,这很难看,但我可以简化为
_name = r"([0-9a-z_:]*)\s*"
_id = r"([1-9])
_type = r"([DGPTE])"
_members = r"([0-9a-z_:,-]*)"
_vhs = r"([1-9-])"
_used = r"([0-9.]*[KMGTPE])"
_size = r"([0-9.]*[KMGTPE])"
_disk_protections_regex_string = r"{0}\s*{1}\s*{2}\s*{3}\s*{4}\s*{5}.*?{6}".format(
_name,
_id,
_type,
_members,
_vhs,
_used,
_size,)
然后我发现我必须用这种格式解析文件
s200_13tb_400gb 1 +3 system, vhs_de 1:0-23, 1 53T / 218T (25% )
-ssd_48gb-ram ny_writes, vhs 2:0-23, 3:0-
_hide_spare, 1,3-19,21-25
ssd_metadata , 4:0-23,
5:0-23,
6:0-23,
7:0-23,
8:0-23,
9:0-23,
10:0-23,
11:0-23,
12:0-23,
13:0-23,
14:0-23,
15:0-23,
16:0-23,
17:0-23,
18:2-25
突然间,期望值变大了
s200_13tb_400gb-ssd_48gb-ram
system vhs_deny_writes, vhs_hide_spare, ssd_metadata
1:0-23, 2:0-23, 3:0-1,3-19,21-25, 4:0-23, 5:0-23, 6:0-23, 7:0-23, 8:0-23, 9:0-23, 10:0-23, 11:0-23, 12:0-23, 13:0-23, 14:0-23, 15:0-23, 16:0-23, 17:0-23, 18:0-23,
以及我提供的原始格式。我甚至不知道从哪里开始使用空格分隔的列分隔值 为列定义切片,然后聚合每行中的数据
col_1 = slice(17)
col_2 = slice(25,40)
col_3 = slice(41,54)
col_4 = slice(55,None)
one, two, three, four = list(), list(), list(), list()
with open('file.txt') as f:
for line in f:
one.append(line[col_1])
two.append(line[col_2])
three.append(line[col_3])
four.append(line[col_4])
print ''.join(item.strip() for item in one)
print ''.join(item.strip() for item in two)
print ''.join(item.strip() for item in three)
print ''.join(item.strip() for item in four)
>>>
s200_13tb_400gb-ssd_48gb-ram
system, vhs_deny_writes, vhs_hide_spare,ssd_metadata
1:0-23,2:0-23, 3:0-1,3-19,21-25, 4:0-23,5:0-23,6:0-23,7:0-23,8:0-23,9:0-23,10:0-23,11:0-23,12:0-23,13:0-23,14:0-23,15:0-23,16:0-23,17:0-23,18:2-25
53T / 218T (25% )
>>>
这将从示例中所示的准直格式中提取数据。如果一个文件中有多条记录,则需要确定记录分隔符。我创建了一个更具动态性的方法,该方法可以自行查找列定义 解释
+[len(content[0])]
在末尾添加一个额外的空白列,以便在需要时访问最后一个数据列import re
from collections import Counter
# Patterns to save in the end, [name, attr, values]
patterns = [r"^([0-9a-z_-]{4,}$)", r"^([a-z_,\s]*$)", r"([0-9:,\s-]{4,})$"]
# Get file content, remove any trailing empty line.
with open('/path/to/my/file') as f:
content = f.read().split('\n')
if not content[-1]:
content = content[:-1]
# 1) Find all single character columns in content with only whitespaces.
no_lines = len(content)
whitespaces = [i for l in content for i, char in enumerate(l) if char == ' ']
whi_columns = [k for k, v in Counter(whitespaces).iteritems() if v == no_lines]
# .items() in python3
# 2) Get all real columns that are between whitespace columns.
columns_defs = []
for i, whi_col in enumerate(whi_columns + [len(content[0])]):
if whi_col and not i: #special first column
columns_defs.append(slice(whi_col))
if whi_col > whi_columns[i - 1] + 1:
columns_defs.append(slice(whi_columns[i - 1] + 1, whi_col))
# 3) Extract columns from file content.
data_columns = [[line[col].strip() for line in content] for col in columns_defs]
# 4) Save columns fitting patterns.
for data_col in data_columns:
data = ''.join(data_col)
if re.match(r'|'.join(patterns), data):
print data
输出
s200_13tb_400gb-ssd_48gb-ram
system, vhs_deny_writes, vhs_hide_spare,ssd_metadata
1:0-23,2:0-23, 3:0-1,3-19,21-25, 4:0-23,5:0-23,6:0-23,7:0-23,8:0-23,9:0-23,10:0-23,11:0-23,12:0-23,13:0-23,14:0-23,15:0-23,16:0-23,17:0-23,18:2-25
“Whitespace delimited”=制表符、空格或任何组合?看起来只是空格,但考虑到我在这些文件中发现的格式差异,目前我不做任何假设。您的输入是否与第三列的第二行、第三行和第四行一样未对齐,还是输入错误?很遗憾,提供的数据是文件的精确复制和粘贴。每个文件是否有多条记录(对于准直格式)?如果是这样的话,是否有任何关于它们是如何分隔的迹象?这使得人们大量假设每一列的宽度都是相同的。阅读评论:“考虑到我在这些文件中发现的格式上的巨大差异,我不做任何假设。”确实如此,但OP文章中的信息是有限的,没有提出任何实际问题。这试图解决文章中的“我甚至不知道从哪里开始使用空格分隔的列分隔值”语句。实际上,这使我更接近于解决问题。看起来(遗憾的是)根据生成文件的代码库版本的不同,有不同的列宽。但这就把问题变成了确定版本,并根据找到的版本使用不同的宽度。更简单的问题。第一行的那些加上三的数字看起来确实像是分隔符——不管从视觉上看。
s200_13tb_400gb-ssd_48gb-ram
system, vhs_deny_writes, vhs_hide_spare,ssd_metadata
1:0-23,2:0-23, 3:0-1,3-19,21-25, 4:0-23,5:0-23,6:0-23,7:0-23,8:0-23,9:0-23,10:0-23,11:0-23,12:0-23,13:0-23,14:0-23,15:0-23,16:0-23,17:0-23,18:2-25