根据另一个文件的信息从一个文件中提取行和子字符串

时间:2013-05-30 12:33:09

标签: string bash sed awk fasta

我有一个文件1.blast,其中包含这样的坐标信息

1       gnl|BL_ORD_ID|0 100.00  33      0       0       1        3
27620   gnl|BL_ORD_ID|0 95.65   46      2       0       1       46
35296   gnl|BL_ORD_ID|0 90.91   44      4       0       3       46
35973   gnl|BL_ORD_ID|0 100.00  45      0       0       1       45
41219   gnl|BL_ORD_ID|0 100.00  27      0       0       1       27
46914   gnl|BL_ORD_ID|0 100.00  45      0       0       1       45 

以及包含此类

等序列信息的文件1.fasta
>1
TCGACTAGCTACGACTCGGACTGACGAGCTACGACTACGG
>2
GCATCTGGGCTACGGGATCAGCTAGGCGATGCGAC
...
>100000
TTTGCGAGCGCGAAGCGACGACGAGCAGCAGCGACTCTAGCTACTG

我现在正在搜索一个脚本,该脚本从1.blast获取第一列并提取那些序列ID(=第一列$1)加序列,然后从序列本身除了{{{{1}之外的所有位置来自$7文件的1}}和$8,意思是前两个匹配输出将是

1.fasta

(请注意>1 ACTAGCTACGACTCGGACTGACGAGCTACGACTACGG >27620 GTAGATAGAGATAGAGAGAGAGAGGGGGGAGA ... 中的前三个条目不在此序列中)

ID是连续的,这意味着我可以提取所需的信息:

>1

这给了我一个矩阵,在第一列中包含右序列标识符行,在第二列中包含右序列行(= ID行后面的一行),然后是应排除的两个坐标。所以基本上是一个包含所有必需信息的矩阵,应该提取awk '{print 2*$1-1, 2*$1, $7, $8}' 1.blast 中的元素

不幸的是,我没有太多的脚本编写经验,因此我现在有点迷失,如何提供值,例如在适当的1.fasta命令? 我可以得到这样的特定行:

sed

和我要删除的字符串,例如通过

sed -n 3,4p 1.fasta

但我现在的问题是,如何将第一个sed -n 5p 1.fasta | awk '{print substr($0,2,5)}' 调用中的信息传输到其他命令中,以便它们提取正确的行并从序列行中删除给定的坐标。所以,awk不是正确的命令,我需要一个命令substr,它从给定的字符串中删除这两个位置之间的所有内容,但我认为我可以在自己的脚本中执行。特别是正确的管道对我来说是一个问题。

4 个答案:

答案 0 :(得分:2)

如果您使用生物信息学并使用DNA序列(甚至更复杂的事情,如序列注释),我建议您查看Bioperl。这显然需要Perl的知识,但具有相当多的功能。

在您的情况下,您希望使用Bio::Seq objects从您的fasta文件生成Bio::SeqIO module

然后,您需要将fasta-entry-numbers和想要的位置读入哈希。使用fasta-name作为键,值是要提取的每个子序列的两个值的数组。如果每个fasta-entry可以有多个这样的子序列,则必须创建一个数组数组作为每个键的值条目。

使用此数据结构,您可以继续使用subseq method from Bio::Seq提取序列。

我希望这是一种适合你的方式,虽然我确信这对纯粹的bash来说也是可行的。

答案 1 :(得分:2)

这不是答案,而是试图澄清你的问题;如果我的任务性质正确,请告诉我。

foreach row in blast:
    get the proper (blast[$1]) sequence from fasta
    drop bases (blast[$7..$8]) from sequence
    print blast[$1], shortened_sequence 

如果我的任务正确无误,那么您的编程语言(bash)以及数据的特殊格式(跨行的记录)会受到影响。 Perl或Python更适合这项任务;事实上Perl的编写部分是因为当时awk中的多个文件访问真的很难,如果不是不可能的话。

你使用你所知道的工具已经走得很远,但看起来你正在达到方便表达的极限。

答案 2 :(得分:1)

更新了答案:

awk  '
NR==FNR && NF { 
    id=substr($1,2)
    getline seq
    a[id]=seq
    next 
} 
($1 in a) && NF { 
    x=substr(a[$1],$7,$8)
    sub(x, "", a[$1])
    print ">"$1"\n"a[$1]
} ' 1.fasta 1.blast

答案 3 :(得分:1)

正如 thunk msw 指出的那样,更适合此类任务的工具可用,但在这里你有一个脚本可以教你如何使用awk处理它:

script.awk 的内容:

## Process first file from arguments.
FNR == NR {
        ## Save ID and the range of characters to remove from sequence.
        blast[ $1 ] = $(NF-1) " " $NF
        next
}

## Process second file. For each FASTA id...
$1 ~ /^>/ {
        ## Get number.
        id = substr( $1, 2 )

        ## Read next line (the sequence).
        getline sequence

        ## if the ID is one found in the other file, get ranges and
        ## extract those characters from sequence.
        if ( id in blast ) {
                split( blast[id], ranges )
                sequence = substr( sequence, 1, ranges[1] - 1 ) substr( sequence, ranges[2] + 1 )
                ## Print both lines with the shortened sequence.
                printf "%s\n%s\n", $0, sequence
        }

}

假设您1.blasta的问题和自定义1.fasta来测试它:

>1
TCGACTAGCTACGACTCGGACTGACGAGCTACGACTACGG
>2
GCATCTGGGCTACGGGATCAGCTAGGCGATGCGAC
>27620
TTTGCGAGCGCGAAGCGACGACGAGCAGCAGCGACTCTAGCTACTGTTTGCGA 

运行如下脚本:

awk -f script.awk 1.blast 1.fasta

产量:

>1
ACTAGCTACGACTCGGACTGACGAGCTACGACTACGG
>27620
TTTGCGA

当然我在假装一些东西,最重要的是fasta序列不超过一行。