Python 比循环整个文件更好的正则表达式实现?
我有这样的文件:Python 比循环整个文件更好的正则表达式实现?,python,regex,python-3.x,shell,text,Python,Regex,Python 3.x,Shell,Text,我有这样的文件: # BJD K2SC-Flux EAPFlux Err Flag Spline 2457217.463564 5848.004 5846.670 6.764 0 0.998291 2457217.483996 6195.018 6193.685 6.781 1 0.998291 2457217.504428 6396.612 6395.278 6.790 0 0.998292 2457217.524861 6220.890 6219.556 6.782 0
# BJD K2SC-Flux EAPFlux Err Flag Spline
2457217.463564 5848.004 5846.670 6.764 0 0.998291
2457217.483996 6195.018 6193.685 6.781 1 0.998291
2457217.504428 6396.612 6395.278 6.790 0 0.998292
2457217.524861 6220.890 6219.556 6.782 0 0.998292
2457217.545293 5891.856 5890.523 6.766 1 0.998292
2457217.565725 5581.000 5579.667 6.749 1 0.998292
2457217.586158 5230.566 5229.232 6.733 1 0.998292
2457217.606590 4901.128 4899.795 6.718 0 0.998293
2457217.627023 4604.127 4602.793 6.700 0 0.998293
我需要查找并计数带有Flag=1的行。(第五栏)我就是这样做的:
foundlines=[]
c=0
import re
with open('examplefile') as f:
for index, line in enumerate(f):
try:
found = re.findall(r' 1 ', line)[0]
foundlines.append(index)
print(line)
c+=1
except:
pass
print(c)
在Shell中,我只需执行
grep“1”examplefile | wc-l
,这比上面的Python脚本要短得多。python脚本可以工作,但我感兴趣的是,是否有比上面的脚本更短、更紧凑的方法来完成任务?我更喜欢Shell的简短,所以我希望在Python中有类似的东西。您的Shell实现可以更简短,grep
有-c
选项来获取计数,无需匿名管道和wc
:
grep -c " 1 " examplefile
shell代码只需获取模式
1
所在的行数,但是Python代码还保留了模式匹配所在行的索引列表
只需获得行数,就可以使用sum
和genexp/list comprehension,也不需要Regex;简单字符串\uuuu包含\uuuu
检查将执行以下操作,因为字符串是可编辑的:
with open('examplefile') as f:
count = sum(1 for line in f if ' 1 ' in line)
print(count)
如果您也想保留索引,您可以坚持您的想法,只需将re
test替换为str
test:
count = 0
indexes = []
with open('examplefile') as f:
for idx, line in enumerate(f):
if ' 1 ' in line:
count += 1
indexes.append(idx)
此外,做一个简单的
Exception
几乎总是一个坏主意(至少你应该使用Exception
来省略SystemExit
,键盘中断
类似异常),只捕获你知道可能引发的异常
此外,在解析结构化数据时,您应该使用特定的工具,例如此处csv.reader
,以空格作为分隔符(line.split(“”)
在这种情况下也应该这样做),并根据索引4进行检查将是最安全的(请参阅)。使用第行中的“1”测试,如果任何其他列包含1
,则会产生误导性结果
考虑到上述情况,以下是使用awk
匹配第5个字段的shell方式:
awk '$5 == "1" {count+=1}; END{print count}' examplefile
如果您有CSV数据,您可以使用CSV
模块:
import csv
with open('your file', 'r', newline='', encoding='utf8') as fp:
rows = csv.reader(fp, delimiter=' ')
# generator comprehension
errors = (row for row in rows if row[4] == '1')
for error in errors:
print(error)
最短代码
在某些特定前提下,这是一个非常简短的版本:
- 您只需要像您的grep调用一样计算发生次数
- 保证每行只有一个
“1”
“1”
只能出现在所需的列中
- 你的文件很容易放入内存
请注意,如果不满足这些前提条件,可能会导致内存问题或返回误报
print(open("examplefile").read().count(" 1 "))
简单多用,略长
当然,如果你对这些台词有兴趣,我推荐熊猫:
df = pandas.read_table('test.txt', delimiter=" ",
comment="#",
names=['BJD', 'K2SC-Flux', 'EAPFlux', 'Err', 'Flag', 'Spline'])
要获取标志为1的所有行,请执行以下操作:
flaggedrows = df[df.Flag == 1]
返回:
BJD K2SC-Flux EAPFlux Err Flag Spline
1 2.457217e+06 6195.018 6193.685 6.781 1 0.998291
4 2.457218e+06 5891.856 5890.523 6.766 1 0.998292
5 2.457218e+06 5581.000 5579.667 6.749 1 0.998292
6 2.457218e+06 5230.566 5229.232 6.733 1 0.998292
要计算它们:
print(len(flaggedrows))
返回4 因为代码工作,您应该考虑将此发布到AT。但是,很明显,在空格之间查找1
不需要正则表达式,如果行中有“1”,请使用。Python中的大多数内容可以放在一行上,但这会严重损害可读性。你确定尺寸对你来说是唯一重要的东西吗?如果你喜欢短的,就用shell。是的,如果可读性比我不介意长的话。好的,我将重新考虑shell实现<代码>。。。如果第
行中的“1”是不可靠的。@Tomalak我承认;)按照字面上的例子。那么你至少应该警告误报的风险。这里是否存在误报的危险,正如这里提到的@heemayl我添加了警告和更好的答案