如何解决使用正则表达式python从文件中提取值的简单方法
您好,我目前正在以python学习Regex,为自己做了一个简单的练习,其中有一个充满数据行的文件,我只想从其中包含“外”的每一行中提取一个值。
file.txt
ABC 134234ed6 outer +
deE 325353ed5 out +
ABC 133234ed0 outer +
deE 325353ed5 out +
ABC 135234ed0 outer +
deE 125353ed5 out +
ABC 455234ed0 outer +
deE 125353ed5 out +
在这里,我只需要获取其中有ed
的每一行中outer
之后的数字(6,0)。 我的代码当前正在运行,但我想知道是否只有使用正则表达式的简化方法。
这是我的代码:
main.py
import re
with open('file.txt') as f:
lines = f.readlines()
regex = re.compile(r'\d +(outer) \+$')
results = []
for line in lines:
match = regex.search(line)
if match:
result = match.group()
results.append(int(result.split(' ')[0])) # this
print(results)
它打印出我想要的[6,0]
。但是逻辑涉及拆分字符串,然后获取第一项(标记为# this
的行),我相信可以将其直接放入正则表达式中,并且可以直接使用group()
提取值。>
我知道已经存在类似的问题,但是我想我的问题足够具体,您只需帮助我简化逻辑,谢谢!
解决方法
您可以重构代码并删除所有多余的正则表达式拆分,匹配项:
import re
with open('file.txt') as f:
lines = f.readlines()
reg = re.compile(r'(\d+) +outer \+$')
results = []
for line in lines:
m = reg.search(line)
if m:
results.append( int(m.group(1)) )
print (results)
输出:
[6,0]
RegEx详细信息:
-
(\d+)
+: Match 1+ digits and capture this in group #1 followed by 1+ spaces. Note that you are only interested in getting this value
(\ d +)`,因此在捕获组中使用它。 -
outer \+
:匹配outer
,后跟一个空格和+
字符 -
$
:比赛结束
基本要点是,对于要提取的正则表达式部分,应使用分组括号。最小的解决方法是将()
放在\d
而不是outer
周围,以便您可以使用match.group(1)
-请参阅anubhava的答案。除此之外,由于您实际上已经将整个文件读入内存,因此很明显不必一次读取一行来减少内存,因此您实际上可以将其读为字符串,然后使用{{1} }。这将有助于简化代码。示例:
re.finditer
这给出了:
import re
with open('file.txt') as f:
text = f.read()
regex = re.compile(r'(\d) +outer \+\n')
results = [int(match.group(1)) for match in regex.finditer(text)]
print(results)
请注意,正则表达式中现在有[6,0]
(换行符)来替换原始正则表达式中的\n
- $
之后必须换行。
附录
要回答一个问题,如果文件确实很大,该怎么办:就像如果无法使用outer \+
那样会超过可用内存一样,您也不能使用f.readlines()
。最好的方法可能是以下方法(类似于anubhava的答案,但避免使用f.read()
)。请注意,在正则表达式中使用捕获组的基本问题仍然相同。
readlines
,
案例1:"outer"
(如果存在)必须遵循"edX"
在这种情况下,您可以将字符串与正则表达式匹配
r'(?<=ed)\d+(?=.*\bouter\b)'
如果有匹配项,它将是"ed"
之后的数字。
Python的正则表达式引擎执行以下操作。
(?<=ed) : positive lookbehind asserts that current position
is immediately preceded by 'ed'
\d+ : match 1+ digits
(?=.*\bouter\b) : positive lookahead asserts that current match is
followed by 0+ characters other than line terminators,followed by 'outer' with word boundaries
情况2:"outer"
(如果存在)可以在"edX"
之前或之后
在这种情况下,您可以将他的字符串与正则表达式匹配
r'^(?=.*\bouter\b).*ed(\d+)'
如果有匹配项,"ed"
之后的数字将包含在捕获组1中。
Python的正则表达式引擎执行以下操作。
^ : assert beginning of string
(?=.*\bouter\b) : positive lookahead asserts that the string
contains 'outer' with word boundaries
.*ed : match 0+ characters other than line terminators,followed by 'ed'
(\d+) : match 1+ digits in capture group 1
存在单词边界(\b
)是为了避免匹配诸如"router"
和"accouterment"
之类的单词。
import re
with open('file.txt') as f:
lines = f.readlines()
results_str = re.findall(r'.*ed(\d+).*\bouter\b.*\+',''.join(lines))
results = [int(x) for x in results_str]
print(results)
输出:
[6,0]
re.findall 可用于查找字符串中的所有匹配项
返回字符串中所有不重叠匹配项的列表。 如果模式中存在一个或多个捕获组,则返回 组列表;这将是一个元组列表,如果模式 有一个以上的小组。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。