V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐学习书目
Learn Python the Hard Way
Python Sites
PyPI - Python Package Index
http://diveintopython.org/toc/index.html
Pocoo
值得关注的项目
PyPy
Celery
Jinja2
Read the Docs
gevent
pyenv
virtualenv
Stackless Python
Beautiful Soup
结巴中文分词
Green Unicorn
Sentry
Shovel
Pyflakes
pytest
Python 编程
pep8 Checker
Styles
PEP 8
Google Python Style Guide
Code Style from The Hitchhiker's Guide
xiyangyang
V2EX  ›  Python

python 正则表达式高手在否?如何非贪婪的用 python split 分离如下文档

  •  
  •   xiyangyang · 2016-11-10 01:11:38 +08:00 · 3518 次点击
    这是一个创建于 2726 天前的主题,其中的信息可能已经有所发展或是发生改变。

    ">"开头的那行是标题,下面 GGCA 之类的是数据。 需要把文档中所有的标题和数据提取出来,变成两个对应的数组或者 map 。 该如何写正则表达式呢?

    p = re.compile(r'^\>.*?$')
    clusters = re.split(p, content)
    

    上面的代码总是不对,请高手出手看看。

    >HSBGPG Human gene for bone gla protein (BGP) (this is name of sequence) GGCAGATTCCCCCTAGACCCGCCCGCACCATGGTCAGGCATGCCCCTCCTCATCGCTGGGCACAGCCCAGAGGGT ATAAACAGTGCTGGAGGCTGGCGGGGCAGGCCAGCTGAGTCCTGAGCAGCAGCCCAGCGCAGCCACCGAGACACC ATGAGAGCCCTCACACTCCTCGCCCTATTGGCCCTGGCCGCACTTTGCATCGCTGGCCAGGCAGGTGAGTGCCCC CACCTCCCCTCAGGCCGCATTGCAGTGGGGGCTGAGAGGAGGAAGCACCATGGCCCACCTCTTCTCACCCCTTTG >HSGLTH1 Human theta 1-globin gene CCACTGCACTCACCGCACCCGGCCAATTTTTGTGTTTTTAGTAGAGACTAAATACCATATAGTGAACACCTAAGA CGGGGGGCCTTGGATCCAGGGCGATTCAGAGGGCCCCGGTCGGAGCTGTCGGAGATTGAGCGCGCGCGGTCCCGG GATCTCCGACGAGGCCCTGGACCCCCGGGCGGCGAAGCTGCGGCGCGGCGCCCCCTGGAGGCCGCGGGACCCCTG GCCGGTCCGCGCAGGCGCAGCGGGGTCGCAGGGCGCGGCGGGTTCCAGCGCGGGGATGGCGCTGTCCGCGGAGGA CCGGGCGCTGGTGCGCGCCCTGTGGAAGAAGCTGGGCAGCAACGTCGGCGTCTACACGACAGAGGCCCTGGAAAG GTGCGGCAGGCTGGGCGCCCCCGCCCCCAGGGGCCCTCCCTCCCCAAGCCCCCCGGACGCGCCTCACCCACGTTC >comp0_c0_seq1 len=248 path=[418:0-247] TATGAGTCCATTATAACAGCCCTAGGACAAACCAGTAAAAAGAGATCTAGCAAAGAGAGT TGAGGGCATTTGTATCCAAGGCATTAAAACAGAGATTAAAGAGGATTTAAATAGAAATAT TTGATCCCGACAAATACCAAACTAGTAGATGCACCTAAATTAAATAAAGAGCTAGAAGGG

    13 条回复    2016-11-10 14:02:11 +08:00
    eyp82
        1
    eyp82  
       2016-11-10 02:03:39 +08:00
    我不是 re 高手, 另外不清楚你的标题和数据的规则, 写了一个, 不知道是否是你想的样子:
    r'>(.*?)\n([^>]*)'

    上面的 pattern 假设:
    1. 你的标题不强求>必须在每一行的开头(我上面的表达式, 没有在前面加^, 所以没在最开头出现的>也会匹配, 如果要求必须在行首, 可以试一下用 re.MULTILINE)
    2. 你的数据里面不能包含>字符 (上面的正则表达式用>做为终止符, 遇到了就不再继续匹配了)
    --------
    如果发现了错误, 还请帮我指出来, 非常感谢各位.
    eyp82
        2
    eyp82  
       2016-11-10 02:06:31 +08:00
    1. 上面的 re, 我没有在后面那个 match group 里把\n 单独拿出来, 如果你的数据里不想在最后有个\n, 可以把它单独写在()的外面 -->但我看你给的数据中间也是有换行的, 所以我猜其实没什么关系?
    2. 这样转换出来是一个 tuple 的 list, 你用 dict comprehension 之类把它转换成 dict 就可以了
    soratadori
        3
    soratadori  
       2016-11-10 05:11:43 +08:00
    。。。这个是 DNA ?
    blueset
        4
    blueset  
       2016-11-10 06:26:39 +08:00
    试着写了一下,上面的数据应该是没问题。

    re.findall(">(.*?) ([ACGT ]+)(?= ?)", data)

    偶数(含 0 )项是标题,奇数项是数据。
    blueset
        5
    blueset  
       2016-11-10 06:33:56 +08:00
    如果中间分割是换行符的话应该是这样的

    re.findall(">(.*?)\n([ACGT\n]+)", a)
    imn1
        6
    imn1  
       2016-11-10 07:35:26 +08:00
    1.标题和数据怎样区分的?你的原文没有显示出来
    2.数据区结尾就是下个标题的开始么?
    3.为什么指定要非贪婪?作业?这个更应该用贪婪

    In [6]: re.findall(r'>(?P<v>.*?)(?P<vv>[A-Z]{10}[^>]*)', content)
    Out[6]:
    [('HSBGPG Human gene for bone gla protein (BGP) (this is name of sequence) ',
    'GGCAGATTCCCCCTAGACCCGCCCGCACCATGGTCAGGCATGCCCCTCCTCATCGCTGGGCACAGCCCAGAGGGT ATAAACAGTGCTGGAGGCTGGCGGGGCAGGCCAGCTGAGTCCTGAGCAGCAGCCCAGCGCAGCCACCGAGACACC ATGAGAGCCCTCACACTCCTCGCCCTATTGGCCCTGGCCGCACTTTGCATCGCTGGCCAGGCAGGTGAGTGCCCC CACCTCCCCTCAGGCCGCATTGCAGTGGGGGCTGAGAGGAGGAAGCACCATGGCCCACCTCTTCTCACCCCTTTG '),
    ('HSGLTH1 Human theta 1-globin gene ',
    'CCACTGCACTCACCGCACCCGGCCAATTTTTGTGTTTTTAGTAGAGACTAAATACCATATAGTGAACACCTAAGA CGGGGGGCCTTGGATCCAGGGCGATTCAGAGGGCCCCGGTCGGAGCTGTCGGAGATTGAGCGCGCGCGGTCCCGG GATCTCCGACGAGGCCCTGGACCCCCGGGCGGCGAAGCTGCGGCGCGGCGCCCCCTGGAGGCCGCGGGACCCCTG GCCGGTCCGCGCAGGCGCAGCGGGGTCGCAGGGCGCGGCGGGTTCCAGCGCGGGGATGGCGCTGTCCGCGGAGGA CCGGGCGCTGGTGCGCGCCCTGTGGAAGAAGCTGGGCAGCAACGTCGGCGTCTACACGACAGAGGCCCTGGAAAG GTGCGGCAGGCTGGGCGCCCCCGCCCCCAGGGGCCCTCCCTCCCCAAGCCCCCCGGACGCGCCTCACCCACGTTC '),
    ('comp0_c0_seq1 len=248 path=[418:0-247] ',
    'TATGAGTCCATTATAACAGCCCTAGGACAAACCAGTAAAAAGAGATCTAGCAAAGAGAGT TGAGGGCATTTGTATCCAAGGCATTAAAACAGAGATTAAAGAGGATTTAAATAGAAATAT TTGATCCCGACAAATACCAAACTAGTAGATGCACCTAAATTAAATAAAGAGCTAGAAGGG')]
    注释:
    1.(?P<变量名>...) 在 findall 中没意义,但在 match 中可以赋值
    2.[A-Z]{10} 这个是标题与数据的分界,原题中没有明确规则,所以这里是随便找的,不通用;如果定下规则就取代这个
    imn1
        7
    imn1  
       2016-11-10 08:05:47 +08:00
    补充: findall 中不能使用两个非贪婪*模糊匹配,结果是不可预料的,我觉得这个算是 re 的 bug , php/js 同样写法是可以预期结果的
    freestyle
        8
    freestyle  
       2016-11-10 08:59:34 +08:00 via iPhone
    把你的*替换成+就是非贪婪的了
    ```Python
    p = re.compile(r'^\>.+?$')
    clusters = re.split(p, content)
    ```
    wjidea
        9
    wjidea  
       2016-11-10 10:50:13 +08:00
    遇到一只生物狗啊,握爪。

    我觉得你可以用 itertools 里面的 groupby 来实现。

    请看下面的 git-gist

    <script src="https://gist.github.com/wjidea/1d26b6340384f3c2e6b2c22ff6425077.js"></script>
    onlrrr
        10
    onlrrr  
       2016-11-10 11:28:44 +08:00
    一个生物专业的大神从我背后路过让我回复 from Bio import SeqIO ,我什么都不知道。
    czheo
        11
    czheo  
       2016-11-10 11:36:32 +08:00
    cluster = {l[0]: l[1] for l in [s.strip().split("\n", 1) for s in content.split(">")] if len(l) == 2}
    laoyur
        12
    laoyur  
       2016-11-10 11:59:48 +08:00
    楼主,你这个原文格式很重要啊,我复制下来粘贴到 sublime ,发现明明就是一行数据,用 re 来弄不太靠谱,因为中间的分隔符都是空格
    你先以 > 进行 split ,拿到各个块,然后各块按空格 split ,最后一个分组就是你要的数据,之前的就是标题
    hanbaobao2005
        13
    hanbaobao2005  
       2016-11-10 14:02:11 +08:00
    re.split() 的结果不会包含分割符,如果需要 titlte 和内容,建议使用 re.finditer, 然后再根据.start(), .end()获取相关的内容。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   888 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 30ms · UTC 21:50 · PVG 05:50 · LAX 14:50 · JFK 17:50
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.