使用Python区分单点行和双点行

使用Python区分单点行和双点行,python,parsing,separator,Python,Parsing,Separator,我有一个大文件,我想以某种方式格式化。文件输入示例: DVL1 03220 NP_004412.2 VANGL2 02758 Q9ULK5 in vitro 12490194 PAX3 09421 NP_852124.1 MEOX2 02760 NP_005915.2 in vitro;yeast 2-hybrid 11423130 VANGL2 02758 Q9ULK5 MAGI3 11290 NP_001136254.1 in vi

我有一个大文件,我想以某种方式格式化。文件输入示例:

DVL1    03220   NP_004412.2 VANGL2  02758   Q9ULK5  in vitro    12490194
PAX3    09421   NP_852124.1 MEOX2   02760   NP_005915.2 in vitro;yeast 2-hybrid 11423130
VANGL2  02758   Q9ULK5  MAGI3   11290   NP_001136254.1  in vitro;in vivo    15195140
这就是我想要它变成的样子:

DVL1    03220   NP_004412   VANGL2  02758   Q9ULK5
PAX3    09421   NP_852124   MEOX2   02760   NP_005915
VANGL2  02758   Q9ULK5  MAGI3   11290   NP_001136254
总结如下:

  • 如果该行有1个点,则该点将与其后面的数字一起删除,并添加一个\t,因此输出行将只有6个制表符分隔的值
  • 如果该行有2个点,则删除这些点以及它们后面的数字,并添加一个\t,因此输出行将只有6个制表符分隔的值
  • 如果该行没有点,则保留前6个制表符分隔的值
我现在的想法是这样的:

for line in infile:
    if "." in line: # thought about this and a line.count('.') might be better, just wasn't capable to make it work
        transformed_line = line.replace('.', '\t', 2) # only replaces the dot; want to replace dot plus next first character
        columns = transformed_line.split('\t')
        outfile.write('\t'.join(columns[:8]) + '\n') # if i had a way to know the position of the dot(s), i could join only the desired columns
    else:
        columns = line.split('\t')
        outfile.write('\t'.join(columns[:5]) + '\n') # this is fine
    with open('data1.txt') as f:
        for line in f:
            line=line.split()[:6]
            line=map(lambda x:x[:x.index('.')] if '.' in x else x,line)  #if an element has '.' then
                                                                         #remove that dot else keep the element as it is
            print('\t'.join(line))
希望我能解释清楚。 谢谢你们的努力

import re
with open(filename,'r') as f:
    newlines=(re.sub(r'\.\d+','',old_line) for old_line in f)
    newlines=['\t'.join(line.split()[:6]) for line in newlines]
现在您有了一个删除了“.number”部分的行列表。据我所知,你的问题还没有被很好地约束到用正则表达式一次就可以完成整个过程,但是用正则表达式2就可以了


现在您有了一个删除了“.number”部分的行列表。据我所知,您的问题还没有很好地约束到使用regex只需一次就可以完成整个过程,但是使用2次就可以了。

您可以尝试以下方法:

for line in infile:
    if "." in line: # thought about this and a line.count('.') might be better, just wasn't capable to make it work
        transformed_line = line.replace('.', '\t', 2) # only replaces the dot; want to replace dot plus next first character
        columns = transformed_line.split('\t')
        outfile.write('\t'.join(columns[:8]) + '\n') # if i had a way to know the position of the dot(s), i could join only the desired columns
    else:
        columns = line.split('\t')
        outfile.write('\t'.join(columns[:5]) + '\n') # this is fine
    with open('data1.txt') as f:
        for line in f:
            line=line.split()[:6]
            line=map(lambda x:x[:x.index('.')] if '.' in x else x,line)  #if an element has '.' then
                                                                         #remove that dot else keep the element as it is
            print('\t'.join(line))
输出:

DVL1    03220   NP_004412   VANGL2  02758   Q9ULK5
PAX3    09421   NP_852124   MEOX2   02760   NP_005915
VANGL2  02758   Q9ULK5  MAGI3   11290   NP_001136254
编辑:

DVL1    03220   NP_004412   VANGL2  02758   Q9ULK5
PAX3    09421   NP_852124   MEOX2   02760   NP_005915
VANGL2  02758   Q9ULK5  MAGI3   11290   NP_001136254

正如@mgilson所建议的那样,行
line=map(lambda x:x[:x.index('.)]if'.'在x else x中,line)
可以简单地替换为
line=map(lambda x:x.split('.)[0],line)
您可以尝试以下方法:

for line in infile:
    if "." in line: # thought about this and a line.count('.') might be better, just wasn't capable to make it work
        transformed_line = line.replace('.', '\t', 2) # only replaces the dot; want to replace dot plus next first character
        columns = transformed_line.split('\t')
        outfile.write('\t'.join(columns[:8]) + '\n') # if i had a way to know the position of the dot(s), i could join only the desired columns
    else:
        columns = line.split('\t')
        outfile.write('\t'.join(columns[:5]) + '\n') # this is fine
    with open('data1.txt') as f:
        for line in f:
            line=line.split()[:6]
            line=map(lambda x:x[:x.index('.')] if '.' in x else x,line)  #if an element has '.' then
                                                                         #remove that dot else keep the element as it is
            print('\t'.join(line))
输出:

DVL1    03220   NP_004412   VANGL2  02758   Q9ULK5
PAX3    09421   NP_852124   MEOX2   02760   NP_005915
VANGL2  02758   Q9ULK5  MAGI3   11290   NP_001136254
编辑:

DVL1    03220   NP_004412   VANGL2  02758   Q9ULK5
PAX3    09421   NP_852124   MEOX2   02760   NP_005915
VANGL2  02758   Q9ULK5  MAGI3   11290   NP_001136254

正如@mgilson所建议的那样,line
line=map(lambda x:x[:x.index('.)]if.'in x else x,line)
可以简单地替换为
line=map(lambda x:x.split('.)[0],line)
我认为应该用一个正则表达式来实现这一点,所以

import re
beast_regex = re.compile(r'(\S+)\s+(\S+)\s+(\S+?)(?:\.\d+)?\s+(\S+)\s+(\S+)\s+(\S+?)(?:\.\d+)?\s+in.*')
with open('data.txt') as infile:
    for line in infile:
        match = beast_regex.match(line)
        print('\t'.join(match.groups())

我想应该有人用一个正则表达式来做这个,所以

import re
beast_regex = re.compile(r'(\S+)\s+(\S+)\s+(\S+?)(?:\.\d+)?\s+(\S+)\s+(\S+)\s+(\S+?)(?:\.\d+)?\s+in.*')
with open('data.txt') as infile:
    for line in infile:
        match = beast_regex.match(line)
        print('\t'.join(match.groups())

您可以使用一个简单的正则表达式:

import re
for line in infile:
    line=re.sub(r'\.\d+','\t',line)
columns = line.split('\t')
outfile.write('\t'.join(columns[:5]) + '\n')

这将用制表符替换后跟一个或多个数字的任何“.”。

您可以使用简单的正则表达式:

import re
for line in infile:
    line=re.sub(r'\.\d+','\t',line)
columns = line.split('\t')
outfile.write('\t'.join(columns[:5]) + '\n')


这将用制表符替换后跟一个或多个数字的任何“.”。

这可以通过
sed
轻松完成。我想你想要
python
,因为它是更大程序的一部分(?)是的,这只是函数的一部分。这可以通过
sed
轻松完成。我想你想要
python
,因为它是一个更大程序的一部分(?)是的,这只是一个函数的一部分。你能一步一步地解释一下你做了什么吗?我不太擅长编程。谢谢你的评论。但我猜,为什么在“in”之后?我编辑了我的解决方案,删除了相关行中的
。只需使用
line.split()[0:6]
获取前6列。这是一个了不起的人,只需在打印('\t')后添加一个+'\n'。加入(line),因为输出只有一行。非常感谢!在lambda中,为什么不使用
x.split('.')[0]
?你能一步一步地解释你做了什么吗?我不太擅长编程。谢谢你的评论。但我猜,为什么在“in”之后?我编辑了我的解决方案,我删除了相关行中的
。只需使用
line.split()[0:6]
来获取前6列。这是一个了不起的人,只需在打印('\t')后添加一个+'\n'。加入(行),因为输出只是一个大的行。非常感谢!在你的lambda中,为什么不使用
x.split('.')[0]
?它是一个正则表达式…用空替换“.”后跟一个或多个#”它还没有给出所需的输出。仍在处理它…(我没有意识到第二个点之后的所有内容都应该被截断)。我有这个想法,但我似乎找不到添加行的正确位置。我是否应该这样做:“在infle中为行导入re:new\u line=re.sub(r'\.\d+,'',old\u line)?哇,这是一个非常好的想法。谢谢,我自己永远不会意识到这一点!这是一个regex…它取代了“.”然后是一个或多个带虚无的#它并没有给出所需的输出(目前)。仍在处理它…(我没有意识到第二个点之后的所有内容都应该被截断)。我有了这个想法,但我似乎找不到添加行的正确位置。我是否应该这样做:“import re for line in infle:new#line=re.sub(r'\.\d+','',旧的“\U行)”?哇,这是很好的想法。谢谢,我自己永远不会意识到这一点!(+1)--虽然,这对“
”的位置非常敏感。例如(如果我读对了),你不可能在第一列有“foo.1”。(+1)--虽然,这对“
”的位置非常敏感。例如(如果我读对了),第一列中不可能有“foo.1”。