复杂的python正则表达式

2024-09-26 17:40:14 发布

您现在位置:Python中文网/ 问答频道 /正文

我有很多这样的台词:

EWSR1{ENST00000397938}:r.1_1364_FLI1{ENST00000429175}:r.1046_3051
EML4{ENST00000318522}:r.1_929_EML4{ENST00000318522}:r.903+188_903+220_ALK{ENST00000389048}:r.4080_6220
FUS{ENST00000254108}:r.1_(608)_FUS{ENST00000254108}:r.(819)_937_DDIT3{ENST00000547303}:r.76_872
TCF3{ENST00000262965}:r.1_1795_ins27_PBX1{ENST00000420696}:r.454_6636
EML4{ENST00000318522}:r.?_ALK{ENST00000389048}:r.?

我需要这样的输出:

对于第一个:

EWSR1 ENST00000397938 1 1364
FLI1 ENST00000429175 1046 3051

对于第二个:

EML4 ENST00000318522 1 929
EML4 ENST00000318522 903+188 903+220
ALK ENST00000389048 4080 6220

第三个:

FUS ENST00000254108 1 (608)
FUS ENST00000254108 (819) 937
DDIT3 ENST00000547303 76 872

第四个:

TCF3 ENST00000262965 1 1795
ins27
PBX1 ENST00000420696 454 6636

第五个:

EML4 ENST00000318522 ?
ALK ENST00000389048 ?

我有数百万行,所以我想想出一个正则表达式为这个,但我不能。我创建了一个条件正则表达式,但我确信有一个更优雅更简单的方法。有人能告诉我一个更简单的方法吗?你知道吗

我现在的解决方案:

import re
import sys

string = sys.argv[1]
if '+?' in string or '-?' in string or not "?" in string:
    for i in re.findall('\w*?\{.*?\}:r\.[\(\)\?\+\-\d]*_[\(\)\?\+\-\d]*', string):
        if 'ins' in i:
            print(re.findall('ins[A-Za-z0-9]*', i)[0])
            i = re.sub('ins[A-Za-z0-9]*', "", i)
        print(i.lstrip('_').split('{')[0], re.findall('\{(.*?)\}', i.lstrip('_'))[0], " ".join(i.lstrip('_').split('r.')[-1].split('_')))

else:
    for i in re.findall('\w*?\{.*?\}:r\.\?', string):
        if 'ins' in i:
            print(re.findall('ins[A-Za-z0-9]*', i)[0])
            i = re.sub('ins[A-Za-z0-9]*', "", i)
        print(i.lstrip('_').split('{')[0], re.findall('\{(.*?)\}', i.lstrip('_'))[0], " ".join(i.lstrip('_').split('r.')[-1].split('_')))

Tags: inrestringsplitprintfusinsza
3条回答

首先在(?<=\d|\)|\?)_(?=[a-z])上拆分,最后将记录分开,如下所示:

EWSR1{ENST00000397938}:r.1_1364
FLI1{ENST00000429175}:r.1046_3051
EML4{ENST00000318522}:r.1_929
EML4{ENST00000318522}:r.903+188_903+220
ALK{ENST00000389048}:r.4080_6220
FUS{ENST00000254108}:r.1_(608)
FUS{ENST00000254108}:r.(819)_937
DDIT3{ENST00000547303}:r.76_872
TCF3{ENST00000262965}:r.1_1795
ins27
PBX1{ENST00000420696}:r.454_6636
EML4{ENST00000318522}:r.?
ALK{ENST00000389048}:r.?

See it here at regex101。你知道吗

然后用(\{|}:r\.|_)替换结果为,结果类似于here on regex101。你知道吗

这会给你

EWSR1 ENST00000397938 1 1364
FLI1 ENST00000429175 1046 3051
EML4 ENST00000318522 1 929
EML4 ENST00000318522 903+188 903+220
ALK ENST00000389048 4080 6220
FUS ENST00000254108 1 (608)
FUS ENST00000254108 (819) 937
DDIT3 ENST00000547303 76 872
TCF3 ENST00000262965 1 1795
ins27
PBX1 ENST00000420696 454 6636
EML4 ENST00000318522 ?
ALK ENST00000389048 ?

第一次拆分为“?=[a-zA-Z]”。然后用“[}{:.\r]”拆分

import re
with open('file.txt') as f:
    for l in f:
        print "\n".join(map(lambda x:" ".join(re.split(r'[}{:._r]',x)),re.split(r'_(?=[a-zA-Z])',l.strip('\n'))))+'\n'

下面是一个单正则表达式解决方案,它可能不那么优雅,但很有效:

((?<![^_])ins\d+)_|([a-zA-Z]+[0-9]*)\{([^{}]*)\}:r\.([-()?+\d]+)?(?:_([-()?+\d]+))?

参见regex demo

细节:

  • ((?<![^_])ins\d+)_-第1组捕获ins(前面没有_以外的字符),后面有一个或多个数字,然后是_
  • |-或
  • ([a-zA-Z]+[0-9]*)-1+ASCII字母,后跟0+数字(如果可以混合使用,请使用\w*而不是[0-9]*
  • \{([^{}]*)\}-一个{...}子串,其内容(不能有{})被捕获到组2中
  • :r\.-文字字符序列:r.
  • ([-()?+\d]+)?可选捕获组(ID 3)贪婪地匹配-()?+或数字1次或多次
  • (?:_([-()?+\d]+))?-一个可选的非捕获组匹配_并捕获到组4中与上述相同的子模式。你知道吗

Python demo

import re
regex = r"((?<![^_])ins\d+)_|([a-zA-Z]+[0-9]*)\{([^{}]*)\}:r\.([-()?+\d]+)?(?:_([-()?+\d]+))?"
test = ["EWSR1{ENST00000397938}:r.1_1364_FLI1{ENST00000429175}:r.1046_3051",
    "EML4{ENST00000318522}:r.1_929_EML4{ENST00000318522}:r.903+188_903+220_ALK{ENST00000389048}:r.4080_6220",
    "FUS{ENST00000254108}:r.1_(608)_FUS{ENST00000254108}:r.(819)_937_DDIT3{ENST00000547303}:r.76_872",
    "TCF3{ENST00000262965}:r.1_1795_ins27_PBX1{ENST00000420696}:r.454_6636",
    "EML4{ENST00000318522}:r.?_ALK{ENST00000389048}:r.?"]
res = []
for s in test:
    for match in re.finditer(regex, s):
        tmp = []
        for groupNum in range(0, len(match.groups())):
            if match.group(groupNum+1):
                tmp.append(match.group(groupNum+1))
        res.append(tmp)
print(res)

结果:

[
 ['EWSR1', 'ENST00000397938', '1', '1364'],
 ['FLI1', 'ENST00000429175', '1046', '3051'],

 ['EML4', 'ENST00000318522', '1', '929'],
 ['EML4', 'ENST00000318522', '903+188', '903+220'],
 ['ALK', 'ENST00000389048', '4080', '6220'],

 ['FUS', 'ENST00000254108', '1', '(608)'],
 ['FUS', 'ENST00000254108', '(819)', '937'],
 ['DDIT3', 'ENST00000547303', '76', '872'],

 ['TCF3', 'ENST00000262965', '1', '1795'],
 ['ins27'],
 ['PBX1', 'ENST00000420696', '454', '6636'],

 ['EML4', 'ENST00000318522', '?'],
 ['ALK', 'ENST00000389048', '?']
]

相关问题 更多 >

    热门问题