【问题标题】:using awk to print header name and a substring使用 awk 打印标题名称和子字符串
【发布时间】:2019-11-22 23:45:19
【问题描述】:

我尝试使用此代码打印基因名称的标题,然后根据其位置提取子字符串,但它不起作用

>output_file
cat input_file | while read row; do
        echo $row > temp
        geneName=`awk '{print $1}' tmp`
        startPos=`awk '{print $2}' tmp`
        endPOs=`awk '{print $3}' tmp`
                for i in temp; do
                echo ">${geneName}" >> genes_fasta ;
                echo "awk '{val=substr($0,${startPos},${endPOs});print val}' fasta" >> genes_fasta
        done
done

输入文件

nad5_exon1 250405 250551
nad5_exon2 251490 251884
nad5_exon3 195620 195641
nad5_exon4 154254 155469
nad5_exon5 156319 156548

快速

atgcatgcatgcatgcatgcatgcatgcatgcatgcatgcatgcatgcatgcatgcatgcatgcatgcatgcatgcatgcatgcatgcatgcatgcatgcatgcatgcatgcatgcatgcatgcatgc............

这是我错误的输出文件

>
awk '{val=substr(pull_genes.sh,,);print val}' unwraped_carm_mt.fasta
>
awk '{val=substr(pull_genes.sh,,);print val}' unwraped_carm_mt.fasta
>
awk '{val=substr(pull_genes.sh,,);print val}' unwraped_carm_mt.fasta
>
awk '{val=substr(pull_genes.sh,,);print val}' unwraped_carm_mt.fasta
>
awk '{val=substr(pull_genes.sh,,);print val}' unwraped_carm_mt.fasta
>
awk '{val=substr(pull_genes.sh,,);print val}' unwraped_carm_mt.fasta

输出应该是这样的:

>name1
atgcatgcatgcatgcatgcat
>name2
tgcatgcatgcatgcat
>name3
gcatgcatgcatgcatgcat
>namen....

【问题讨论】:

  • 输入文件(包含少数案例)和预期结果的示例将有助于更好地了解您要完成的工作。
  • 在问题中添加了该信息。谢谢!
  • 看起来不错,但是你真正希望它做的“正确”输出也将是无价的,因为我仍然没有遵循你想要完成的事情。此外,设置变量的awk 行正在查看tmp,但您创建的文件称为temp
  • 请修复 shellcheck.net 发现的问题,然后使用来自示例输入的所需输出更新您的 Q。您知道这可以是一个awk 进程,而不是每行数据5-6 个吗?见grymoire.com/Unix/Awk.html。祝你好运。
  • 您需要删除以下echo "awk '{val=substr($0,${startPos},${endPOs});print val}' fasta" 中的“echo”和双引号。这是命令吧?如果你把 echo 它简单地打印命令并附加到文件中。

标签: bash unix bioinformatics genome google-genomics


【解决方案1】:

您可以通过一次调用 awk 来完成此操作,这将比在 shell 脚本中循环并在每次迭代中调用 awk 4 次效率高出几个数量级。由于您有 bash,您可以简单地使用 command substitution 并将 fasta 的内容重定向到 awk 变量,然后简单地输出标题和包含从您的 @ 开始到结束字符的子字符串987654325@文件。

例如:

awk -v fasta=$(<fasta) '{print ">" $1; print substr(fasta,$2,$3-$2+1)}' input

或在BEGIN 规则中使用getline

awk 'BEGIN{getline fasta<"fasta"}
{print ">" $1; print substr(fasta,$2,$3-$2+1)}' input

输入文件示例

注意:开始和结束值已减少到适合您示例的 129 个字符:

$ cat input
rad5_exon1 1 17
rad5_exon2 23 51
rad5_exon3 110 127
rad5_exon4 38 62
rad5_exon5 59 79

以及示例的前 129 个字符 fasta

$ cat fasta
atgcatgcatgcatgcatgcatgcatgcatgcatgcatgcatgcatgcatgcatgcatgcatgcatgcatgcatgcatgcatgcatgcatgcatgcatgcatgcatgcatgcatgcatgcatgcatgc

使用/输出示例

$ awk -v fasta=$(<fasta) '{print ">" $1; print substr(fasta,$2,$3-$2+1)}' input
>rad5_exon1
atgcatgcatgcatgca
>rad5_exon2
gcatgcatgcatgcatgcatgcatgcatg
>rad5_exon3
tgcatgcatgcatgcatg
>rad5_exon4
tgcatgcatgcatgcatgcatgcat
>rad5_exon5
gcatgcatgcatgcatgcatg

检查一下,如果我理解您的问题要求,请告诉我。如果您对解决方案还有其他问题,也请告诉我。

【讨论】:

    【解决方案2】:

    如果我理解正确,那么:

    awk 'NR==FNR {fasta = fasta $0; next}
        {
            printf(">%s %s\n", $1, substr(fasta, $2, $3 - $2 + 1))
        }' fasta input_file > genes_fasta
    
    
    • 它首先读取fasta文件并将序列存储在变量fasta中。
    • 然后它逐行读取input_file,提取fasta的子字符串,从$2开始,长度为$3 - $2 + 1。 (请注意,substr 函数的第三个参数是长度,而不是 endpos。)

    希望这会有所帮助。

    【讨论】:

    • @ZivAttia 你能具体谈谈still not working吗?
    • 'awk '{val=substr($0,"$startPos","$endPos");print val}' unwraped_${fasta} >>genes_fasta 由于某种原因不起作用。如果我将 startPos 和 endPos 更改为数字,它可以正常工作
    • 它不起作用,现在我只需要修复这一行
    • 正如我在回答中评论的那样,substr 函数的第三个参数是长度,而不是位置。
    • 好的,由于某种原因它不适合我。我尝试使用这个命令 awk -v b="$startPos" -v c="$endPos" '{val=substr($0,$b,$c);print val}' unwraped_${fasta} >>genes_fasta 但它没有也不行。如何在 awk 命令中设置变量?
    【解决方案3】:

    成功了! 这是从 fasta 文件中提取子字符串的脚本

    cat genes_and_bounderies1 | while read row; do
            echo $row > temp
            geneName=`awk '{print $1}' temp`
            startPos=`awk '{print $2}' temp`
            endPos=`awk '{print $3}' temp`
            length=$(expr $endPos - $startPos)
                    for i in temp; do
                    echo ">${geneName}" >> genes_fasta
                    awk -v S=$startPos -v L=$length '{print substr($0,S,L)}' unwraped_${fasta} >> genes_fasta
            done
    done
    

    【讨论】:

    • 很好,很高兴你能成功。但是仔细观察每次迭代产生的子壳的数量。对于 while 循环的每次迭代,在循环 for i in temp; do 之前调用 awk 3 次,然后每次迭代调用一次。首先让它工作没有错,但是要读取一百万行,时间上的差异执行将是几小时而不是几秒。
    • 您建议如何编写它?我是生物学家而不是程序员,我真的很想学习!
    • 我在回答中的写法。您会看到只有一个进程(单个子shell)为整个项目运行awk 的一个实例。在您的代码中,每次迭代至少调用 awk 4 次。单独的程序启动时间以及加载和卸载每个进程使用的数据将增加几个数量级的运行时间。
    猜你喜欢
    • 2020-03-17
    • 2017-02-15
    • 1970-01-01
    • 1970-01-01
    • 2019-10-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-12-16
    相关资源
    最近更新 更多