这是示例.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 . + .
我几乎能够使用此正则表达式\t
(try it here)按(?:21$)|(?:\t*(.*?[^\t]+))
分割(我的行末有问题)。
我还尝试用if else和Negative scaround来分割最后一个元素,但没有结果。
我该怎么做?
答案 0 :(得分:2)
See regex in use here。第二个正则表达式清除该元素as seen here中的空格。
\t|;(?=[^\t;]*$)
\t|;[^\S\t]*(?=[^\t]*$)
匹配以下任一项:
\t
匹配制表符;
按字面意思匹配[^\S\t]*
匹配除\t
之外的任意数量的空白字符。这就是清理第二个正则表达式中的空白的原因。(?=[^\t]*$)
确定以下内容的正向前瞻符合以下内容
[^\t]*
匹配除\t
以外的任何字符$
断言行尾的位置我意识到这可能是一个文件,所以你打开文件,然后在每一行上运行它,但我只是把你放入问题的样本并用splitlines()
分割字符串来模仿那种行为。
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)
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类型语言之间移植。