我有一大块数据(一个文件),如下所示,每一行具有不同数量的列(由制表符分隔),数据结构像 这个:
>NP_12345.1 matchnumber_1_RKHKK
>NP_56789.2 matchnumber_1_HGRR matchnumber_2_KQRHH matchnumber_3_RVRK matchnumber_4_HTHH
>XP_543421.1 matchnumber_1_RQRH ... matchnumber_m_RVRR
...
在上面的文件中,第一行有2列,第二行有5列,第三行有m + 1列...;显然,文件的每一行都有“> accessionID”和“ matchnumber_i_XXX”。我想将每一行的第一列添加到相应行中以“ matchnumber”标记的每一列的开头,并以fasta格式打印出来,输出就像这样:
>NP_12345.1matchnumber_1
RKHKK
>NP_56789.2matchnumber_1
HGRR
>NP_56789.2matchnumber_2
KQRHH
>NP_56789.2matchnumber_3
RVRK
>NP_56789.2matchnumber_4
HTHH
>XP_543421.1matchnumber_1
RQRH
....
>XP_543421.1matchnumber_m
RVRR
...
有人可以帮助我吗?预先感谢。
注意:例如,当存在一个行文件时,文件“ a.txt”只有一个行内容:
>NP_56789.2 matchnumber_1_HGRR matchnumber_2_KQRHH matchnumber_3_RVRK matchnumber_4_HTHH
我可以使用管道化的awk和sed命令来解析数据:
cat a.txt |awk -v OFS="\t" '{print $1$2,$1$3,$1$4,$1$5}' | sed 's/\t/\n/g' | sed 's/_/ /g' | sed 's/NP /NP_/g' | sed 's/matchnumber /matchnumber_/g' | sed 's/ /\n/g' > a.fasta
a.fasta就像愚蠢的人一样
>NP_56789.2matchnumber_1
HGRR
>NP_56789.2matchnumber_2
KQRHH
>NP_56789.2matchnumber_3
RVRK
>NP_56789.2matchnumber_4
HTHH
当a.txt包含多行数据时,我不知道要解决该问题。
答案 0 :(得分:2)
$ cat jfile
>NP_12345.1 matchnumber_1_RKHKK
>NP_56789.2 matchnumber_1_HGRR matchnumber_2_KQRHH matchnumber_3_RVRK matchnumber_4_HTHH
$ awk -F"\t" '{for(i=2;i<=NF;i++){match($i,"(matchnumber_[0-9]+)_(.*)",r);print $1 r[1] ORS r[2];}}' jfile
>NP_12345.1matchnumber_1
RKHKK
>NP_56789.2matchnumber_1
HGRR
>NP_56789.2matchnumber_2
KQRHH
>NP_56789.2matchnumber_3
RVRK
>NP_56789.2matchnumber_4
HTHH
从第二个字段$2
到最后一个字段$NF
,使用match
和regex
取出想要的内容,例如matchnumber_1
和{{ 1}},然后打印。
在awk中,空间仅用于连接,RKHKK
表示行结束,此处有效等于ORS
。 \n
是正则表达式匹配的数组,其中r [0]表示整个匹配的字符串,r [1]和r [2]表示第一对和第二对r
匹配的内容。 -您可以将()
更改为所需的其他变量名称。
对于正则表达式,[0-9]表示任何单个数字,其后的r
表示匹配1个或多个上述字符,此处表示1个或多个连续数字。如上所述,括号仅用于将内容捕获到组中,以供以后参考。每对括号中匹配的内容将保存到我提供的数组的一个元素中,这里为+
。
答案 1 :(得分:2)
awk '{for(i=2;i<=NF;i++){print $1 gensub(/_([^_]+)$/,"\n\\1",1,$i)}}' file
答案 2 :(得分:1)
抢救Perl!
$ cat james.txt
>NP_12345.1 matchnumber_1_RKHKK
>NP_56789.2 matchnumber_1_HGRR matchnumber_2_KQRHH matchnumber_3_RVRK matchnumber_4_HTHH
>XP_543421.1 matchnumber_1_RQRH matchnumber_2_QQQQ
$ perl -lne ' /(^\S+) (.+)/;$pre=$1;$mat=$2;while($mat=~/(match.+?_\d+)_(\S+)/g) { print "$pre $1\n$2" } ' james.txt
>NP_12345.1 matchnumber_1
RKHKK
>NP_56789.2 matchnumber_1
HGRR
>NP_56789.2 matchnumber_2
KQRHH
>NP_56789.2 matchnumber_3
RVRK
>NP_56789.2 matchnumber_4
HTHH
>XP_543421.1 matchnumber_1
RQRH
>XP_543421.1 matchnumber_2
QQQQ
$
说明
perl -lne
# -l to remove newline when reading and add newline when print statement is used
# -n - suppress default printing at the end of each line processing
# -e - for perl on commandline
' /(^\S+) (.+)/;
split line by first word (^\S+) -> matches first column and stores it in $1 since we used () to capture
the second (.+) stores the rest of the text in $2
$pre=$1;$mat=$2;
Assign $1 to $pre and $2 to $mat
while($mat=~/(match.+?_\d+)_(\S+)/g)
Now mat stores from 2nd column to the rest of the line.
// => match with regex and (match.+?_\d+) to capture it in $1
(\S+) => captures the "HGRR"
/g => like this we have many matches.. so 'g'lobally repeat the matching
to get all of them using the while loop. If /g is ignored, then we will just get first match alone.
{ print "$pre $1\n$2" }
Now print $pre, $1 newline and $2 --> This $1 and $2 is local to the while loop and
don't get confused with the earlier $1 and $2 which we assigned to $pre and $mat
for each while loop turn $1 and $2 match different values and get printed.
答案 3 :(得分:1)
另一个perl一个班轮:
perl -anE '($c1,@r)=split/\s+/,$_;for(@r){($c,$v)=$_=~/^(.+)_(.+)$/;say "$c1 $c\n$v"}' file.txt
>NP_12345.1 matchnumber_1
RKHKK
>NP_56789.2 matchnumber_1
HGRR
>NP_56789.2 matchnumber_2
KQRHH
>NP_56789.2 matchnumber_3
RVRK
>NP_56789.2 matchnumber_4
HTHH
>XP_543421.1 matchnumber_1
RQRH
>XP_543421.1 matchnumber_2
RQRH
>XP_543421.1 matchnumber_3
RQRH
说明:
($c1,@r)=split/\s+/,$_; # split allline into 1 col value and rest of the line
for(@r){ # for each lols othar than 1rst one
($c,$v)=$_=~/^(.+)_(.+)$/; # extract before the last underscore and after it
say "$c1 $c\n$v" # print col1 coln linebreak value
}
答案 4 :(得分:1)
Python不擅长使用一行命令,但是很容易使用它来解析文件:
parser.py:
import fileinput
for line in fileinput.input(): # process stdin or files given as parameters
words = line.split() # split the line
for w in words[1:]: # process all words past the first
ix = w.rindex('_') # search last _ in the words
print(words[0] + w[:ix]) # print first line
print(w[ix+1:]) # and second one
然后您可以使用以下任何一种方式:
cat file | python parse.py
或:
python parse.py file
答案 5 :(得分:1)
这可能对您有用(GNU sed):
sed -r ':a;h;/^(\S+)\s+(\S+)_(\S+)\s*(.*)/{s//\1\2\n\3/p;x;s//\1 \4/;ta};d' file
复制当前行。使用模式匹配将模式空间中的第一个字段和第二个字段操纵为所需格式并进行打印。交换到副本,并通过删除第二个字段和随后的任何空白来缩短副本。重复直到模式匹配失败。