由分隔符拆分,由另一个分隔符拆分

时间:2018-04-06 16:43:59

标签: regex split

这是示例.gtf文件的摘录。我需要通过\t分隔符拆分每一行,然后只拆分我;获得的最后一个元素。

X   Ensembl Repeat  2419108 2419128 42  .   .   hid=trf; hstart=1; hend=21
X   Ensembl Repeat  2419108 2419410 2502    -   .   hid=AluSx; hstart=1; hend=303
X   Ensembl Repeat  2419108 2419128 0   .   .   hid=dust; hstart=2419108; hend=2419128
X   Ensembl Pred.trans. 2416676 2418760 450.19  -   2   genscan=GENSCAN00000019335
X   Ensembl Variation   2413425 2413425 .   +   .   
X   Ensembl Variation   2413805 2413805 .   +   .

我几乎能够使用此正则表达式\ttry it here)按(?:21$)|(?:\t*(.*?[^\t]+))分割(我的行末有问题)。 我还尝试用if else和Negative scaround来分割最后一个元素,但没有结果。

我该怎么做?

相关问题:RegEx: Split string by separator and then by another

2 个答案:

答案 0 :(得分:2)

See regex in use here。第二个正则表达式清除该元素as seen here中的空格。

\t|;(?=[^\t;]*$)
\t|;[^\S\t]*(?=[^\t]*$)

匹配以下任一项:

  • 选项1
    • \t匹配制表符
  • 选项2
    • ;按字面意思匹配
    • [^\S\t]*匹配除\t之外的任意数量的空白字符。这就是清理第二个正则表达式中的空白的原因。
    • (?=[^\t]*$)确定以下内容的正向前瞻符合以下内容
      • [^\t]*匹配除\t以外的任何字符
      • $断言行尾的位置

我意识到这可能是一个文件,所以你打开文件,然后在每一行上运行它,但我只是把你放入问题的样本并用splitlines()分割字符串来模仿那种行为。

See code in use here

import re

d = """X    Ensembl Repeat  2419108 2419128 42  .   .   hid=trf; hstart=1; hend=21
X   Ensembl Repeat  2419108 2419410 2502    -   .   hid=AluSx; hstart=1; hend=303
X   Ensembl Repeat  2419108 2419128 0   .   .   hid=dust; hstart=2419108; hend=2419128
X   Ensembl Pred.trans. 2416676 2418760 450.19  -   2   genscan=GENSCAN00000019335
X   Ensembl Variation   2413425 2413425 .   +   .   
X   Ensembl Variation   2413805 2413805 .   +   ."""

print([re.split(r"\t|;[^\S\t]*(?=[^\t]*$)",e) for e in d.splitlines()])

结果:

[
    ['X', 'Ensembl', 'Repeat', '2419108', '2419128', '42', '.', '.', 'hid=trf', 'hstart=1', 'hend=21'],
    ['X', 'Ensembl', 'Repeat', '2419108', '2419410', '2502', '-', '.', 'hid=AluSx', 'hstart=1', 'hend=303'],
    ['X', 'Ensembl', 'Repeat', '2419108', '2419128', '0', '.', '.', 'hid=dust', 'hstart=2419108', 'hend=2419128'],
    ['X', 'Ensembl', 'Pred.trans.', '2416676', '2418760', '450.19', '-', '2', 'genscan=GENSCAN00000019335'],
    ['X', 'Ensembl', 'Variation', '2413425', '2413425', '.', '+', '.', ''],
    ['X', 'Ensembl', 'Variation', '2413805', '2413805', '.', '+', '.']
]

答案 1 :(得分:1)

OP评论说Python正在使用,但其他语言还可以。所以...我不确定这有多少,如果有的话,适用于Python,但我或多或少同意评论,试图用一个正则表达式做这个是愚蠢的。比如,这里的perl或多或少都有2个分割:

perl -F"\t" -lane 'for $i (0..$#F){if ($i!=$#F) {print "$F[$i]"} else {print for split(/;\s?/, $F[$i])}}' input

要解决此问题,-F"\t"会将标签拆分为F数组。然后我循环遍历它并在分号上拆分最后一个元素。并且...这可以作为一个单行,但几乎没有。试图用输出来做更多事情会开始变得荒谬。

但后来我看到@ctwheels回答(这是Perl的等价物):

perl -F'/\t|;[^\S\t]*(?=[^\t]*$)/' -lane 'print for @F' input

这是 awesome 。输入已经分开,一切都在我开始之前完成。 “程序”(print for @F)只是打印结果......意思是如果我还有其他工作要做,我可以很容易地做到。说实话,在它停止伤害我的大脑之前,我只需要盯着它看几分钟。可能比“代码”答案更容易理解,并且基本上可以在任何PCRE类型语言之间移植。