我打算学习regex,并尝试使用它来解决问题。我需要编写一个函数来获得一个VCF文件,并需要检查文件中的一些列,看看它们是否符合要求。
第一列应以"chr"开头,以1-99之间的任何数字或字母"M,X,Y"之一结尾。第二列必须是所有大于0的整数。第4列和第5列需要是下一个字母"ATCG"中的一个(仅为其中一个(。如果其中一个语句即使在一行中也是错误的,那么它应该返回false。
这是我写的代码:
def isVCF(file):
with open(file, "r+") as my_file:
lines = my_file.readlines()
for line in lines:
columns = line.split("t")
num_format = re.compile("^[+]?[1-9][0-9]*.?[0-9]+$")
if (re.match(r"^chr(?:[1-9][0-9]?|[XYM])$", columns[0])
and re.match(num_format, columns[1])
and re.match(r"^[ATGC]$", columns[3])
and re.match(r"^[ATGC]$", columns[4])):
return True
else:
return False
我检查了两个文件——一个应该返回True,另一个应该为False,但我在这两个文件上都得到了True,所以我尝试逐行进行测试,但仍然得到了True。文件示例:
ChrX, 74226650, ., T, C, 50, ., DP=385;VDB=0;SGB=-0.693147;RPB=0.982669;MQB=1;BQB=0.947576;MQ0F=0;AC=2;AN=2;DP4=0,95,0,289;MQ=20, GT:PL:DP, 1/1:78,127,0:384
输出应该是或true或false取决于条件。
感谢您的帮助!
您需要逐一解决问题:
-
第一列应以
chr
开头,以1-99
之间的任何数字或字母M,X,Y
-chr(?:0?[1-9]|[1-9][0-9]|[MXY])
之一结尾 -
第二列必须是大于
0
-0*[1-9][0-9]*
的所有整数 -
第4列和第5列需要是下一个字母"ATCG"之一(仅其中一个(-
[ATCG]
现在,考虑到列分隔符是您在代码示例中使用的分隔符(TAB字符,t
(,您可以使用
def isVCF(file):
num_format = re.compile(r"^chr(?:0?[1-9]|[1-9][0-9]|[MXY])t0*[1-9][0-9]*t[^t]*(?:t[ATCG]){2}t", re.I)
with open(file, "r+") as my_file:
for line in my_file:
if not num_format.match(line):
return False
return False
请参阅regex演示。
注意,我使用re.I
来启用不区分大小写,因为您在问题中同时使用了chr
和Chr
,如果您需要以这种方式仅匹配Chr
和chr
,请删除re.I
并将chr
替换为(?i:chr)
。
详细信息:
^
-字符串的开头chr
(列1的开头(-chr
字符串(?:0?[1-9]|[1-9][0-9]|[MXY])
(第1列末尾(:一个可选的0
,然后是一个非零数字,或者一个从1
到9
的数字,然后是任何一个数字(0
-99
(,或者MXY
集合中的一个字母t
-选项卡0*[1-9][0-9]*
(第2列(:零个或多个0
s,一个非零数字,然后是任何零个或更多数字t
-选项卡[^t]*
(第3列(-除制表符之外的任何零个或多个字符(?:t[ATCG]){2}
(第4列和第5列(-tab,来自ATCG
的一个字母集,两次t
-一个选项卡