我的问题:如何根据正则表达式模式匹配分配字典键,从列表中创建字典(' ^ - L- [0-9] {8} '),并使用每个键之间的所有行来分配值。
原始文件的示例摘录:
SQL> --L-93752133
SQL> --SELECT table_name, tablespace_name from dba_tables where upper(table_name) like &tablename_from_developer;
SQL>
SQL> --L-52852243
SQL>
SQL> SELECT log_mode FROM v$database;
LOG_MODE
------------
NOARCHIVELOG
SQL>
SQL> archive log list
Database log mode No Archive Mode
Automatic archival Disabled
Archive destination USE_DB_RECOVERY_FILE_DEST
Oldest online log sequence 3
Current log sequence 5
SQL>
SQL> --L-42127143
SQL>
SQL> SELECT t.name "TSName", e.encryptionalg "Algorithm", d.file_name "File Name"
2 FROM v$tablespace t
3 , v$encrypted_tablespaces e
4 , dba_data_files d
5 WHERE t.ts# = e.ts#
6 AND t.name = d.tablespace_name;
no rows selected
一些额外的细节:原始文件可能很大(至少80K +行,但通常要大得多),我需要保留原始间距,以便输出仍然易于阅读。这是我如何阅读文件并删除" SQL>"从每行的开头:
with open(rawFile, 'r') as inFile:
content = inFile.read()
rawList = content.splitlines()
for line in rawList:
cleanLine = re.sub('^SQL> ', '', line)
查找我正在寻找的字典键非常简单:
pattern = re.compile(r'^--L-[0-9]{8}')
if pattern.search(cleanLine) is not None:
itemID = pattern.search(cleanLine)
print(itemID.group(0))
但是,如何将每个键之间的所有行分配为属于它们之前的最新键的值?我一直在玩新的列表,元组和字典,但我所做的一切都是回垃圾。目标是让数据和密钥相互链接,以便我可以在以后的脚本中根据需要返回它们。
我花了一段时间搜索类似的问题,但在大多数其他情况下,源文件已经是类似字典的格式,因此创建新字典是一个不太复杂的问题。也许字典或元组不是正确的答案,但任何帮助将不胜感激!谢谢!
答案 0 :(得分:1)
这样的东西?
with open(rawFile, 'r') as inFile:
content = inFile.read()
rawList = content.splitlines()
keyed_dict = {}
in_between_lines = ""
last_key = 0
for line in rawList:
cleanLine = re.sub('^SQL> ', '', line)
pattern = re.compile(r'^--L-[0-9]{8}')
if pattern.search(cleanLine) is not None:
itemID = pattern.search(cleanLine)
if last_key: keyed_dict[last_key] = in_between_lines
last_key = itemID.group(0)
in_between_lines = ""
else:
in_between_lines += cleanLine
答案 1 :(得分:1)
通常,您应该质疑为什么要读取整个文件,将行拆分为列表,然后遍历列表。这是一个Python反模式。
对于面向行的文本文件,只需执行:
with open(fn) as f:
for line in f:
# process a line
然而,听起来你有多线块面向模式。如果是这样,使用较小的文件,将整个文件读入单个字符串并使用正则表达式。然后你将使用组1和组2作为你的词典中的键值:
pat=re.compile(pattern, flags)
with open(file_name) as f:
di={m.group(1):m.group(2) for m in pat.finditer(f.read())}
如果文件较大,请使用mmap
:
import re, mmap
pat=re.compile(pattern, flags)
with open(file_name, 'r+') as f:
mm = mmap.mmap(f.fileno(), 0)
for i, m in enumerate(pat.finditer(mm)):
# process each block accordingly...
就正则表达式而言,我对你要捕获的内容有点不清楚。我认为这个正则表达式是我理解你想要的:
^SQL> (--L-[0-9]{8})(.*?)(?=SQL> --L-[0-9]{8}|\Z)
在任何一种情况下,使用示例字符串运行该正则表达式都会产生:
>>> pat=re.compile(r'^SQL> (--L-[0-9]{8})\s*(.*?)\s*(?=SQL> --L-[0-9]{8}|\Z)', re.S | re.M)
>>> with open(file_name) as f:
... di={m.group(1):m.group(2) for m in pat.finditer(f.read())}
...
>>> di
{'--L-52852243': 'SQL> \nSQL> SELECT log_mode FROM v;\n\n LOG_MODE\n ------------\n NOARCHIVELOG\n\nSQL> \nSQL> archive log list\n Database log mode No Archive Mode\n Automatic archival Disabled\n Archive destination USE_DB_RECOVERY_FILE_DEST\n Oldest online log sequence 3\n Current log sequence 5\nSQL>',
'--L-93752133': 'SQL> --SELECT table_name, tablespace_name from dba_tables where upper(table_name) like &tablename_from_developer;\nSQL>',
'--L-42127143': 'SQL> \nSQL> SELECT t.name TSName, e.encryptionalg Algorithm, d.file_name File Name\n 2 FROM v t\n 3 , v e\n 4 , dba_data_files d\n 5 WHERE t.ts# = e.ts#\n 6 AND t.name = d.tablespace_name;\n\n no rows selected'}