避免AWK打印初始空行

时间:2014-12-14 11:43:52

标签: printing awk

我很确定这很简单,但我没有找到与此问题相关的问题。 我正在使用下一个代码打印PosGen.bed第5列中给定基因的第一个起始位点和最终终点位点

awk 'BEGIN{ch=$1;ini=$2;fin=$3;gen=$5}{if(gen==$5){fin=$3}else{print ch"\t"ini"\t"fin"\t"gen;ch=$1;ini=$2;fin=$3;gen=$5}}}END{print ch"\t"ini"\t"fin"\t"gen}' PosGen.bed | head

我所做的是保留第一个网站> BEGIN<。然后,条件if将验证下一行,甚至第一行是否具有相同的基因名称,如果是,则使用新的结束站点刷新结束站点。 如果检测到其他基因名称,它将打印出所有实际信息并将其替换为新基因的信息。我的代码按预期工作,但我无法摆脱那个初始行;这可以很容易地从输出文件中删除,但我很想学习并最终掌握awk ...

所以,问题是:我的代码正在打印一个初始空行,我没有检测到原因,你知道为什么要打印一个空行吗?

我虽然这是因为错误的{braquets},但这似乎不是问题所在。 这是我得到的输出和输入的一个例子。

任何帮助都将受到高度赞赏! 谢谢!

输出文件(我们的朋友是空行)

chr1    3204563 3661429 Xkr4
chr1    4280927 4399268 Rp1
chr1    4481009 4486494 Sox17
chr1    4763279 4775758 Mrpl15

输入文件

chr1 3204563 3207049 - Xkr4
chr1 3206103 3206105 - Xkr4
chr1 3206106 3207049 - Xkr4
chr1 3411783 3411982 - Xkr4
chr1 3411783 3411982 - Xkr4
chr1 3660633 3661429 - Xkr4
chr1 3660633 3661579 - Xkr4
chr1 3661427 3661429 - Xkr4
chr1 4280927 4283093 - Rp1
chr1 4283062 4283064 - Rp1
chr1 4283065 4283093 - Rp1
chr1 4333588 4340172 - Rp1
chr1 4334681 4334683 - Rp1
chr1 4334684 4340172 - Rp1
chr1 4341991 4342162 - Rp1
chr1 4341991 4342162 - Rp1
chr1 4341991 4342162 - Rp1
chr1 4341991 4342162 - Rp1
chr1 4342283 4342906 - Rp1
chr1 4342283 4342918 - Rp1
chr1 4342283 4342918 - Rp1
chr1 4342283 4342918 - Rp1
chr1 4342904 4342906 - Rp1
chr1 4350281 4350395 - Rp1
chr1 4399251 4399268 - Rp1
chr1 4399251 4399322 - Rp1
chr1 4399266 4399268 - Rp1
chr1 4481009 4482749 - Sox17
chr1 4481797 4481799 - Sox17
chr1 4481800 4482749 - Sox17
chr1 4483181 4483487 - Sox17
chr1 4483181 4483547 - Sox17
chr1 4483485 4483487 - Sox17
chr1 4483853 4483944 - Sox17
chr1 4485217 4486023 - Sox17
chr1 4486372 4486494 - Sox17
chr1 4763279 4764597 - Mrpl15

3 个答案:

答案 0 :(得分:2)

}之前还有一个额外的END会导致代码失败(出错),将其删除。

BEGIN部分没有执行任何操作,因为$1,$2 etc在第一行运行之前不包含任何内容。

重写一些代码,使其更容易阅读 由于gen在首次运行时未包含任何内容,因此您if会转到else部分。
它首先要做的是打印ini fingen。并且在第一次运行时,这不包含任何内容,给出空白行(错误使用BEGIN

awk '
BEGIN {
    ch=$1
    ini=$2
    fin=$3
    gen=$5
}
{
    if (gen==$5) {
        fin=$3
    }
    else {
        print ch"\t"ini"\t"fin"\t"gen
        ch=$1
        ini=$2
        fin=$3
        gen=$5
    }
}
END {
    print ch"\t"ini"\t"fin"\t"gen
}
' file

PS在此处发布时,选择代码并单击{}以概述代码。


要解决此问题,请将BEGIN更改为NR==1,使其像第一行一样运行:

awk -v OFS='\t' '
NR==1 {
    ch=$1
    ini=$2
    fin=$3
    gen=$5
}
{
    if (gen==$5) {
        fin=$3
    }
    else {
        print ch, ini, fin, gen
        ch=$1
        ini=$2
        fin=$3
        gen=$5
    }
}
END {
    print ch, ini, fin, gen
}
' file
chr1    3204563 3661429 Xkr4
chr1    4280927 4399268 Rp1
chr1    4481009 4486494 Sox17
chr1    4763279 4764597 Mrpl15

答案 1 :(得分:2)

正如@Jotne指出的那样,你误解了BEGIN的使用 - 它是在第一个输入文件被打开阅读之前执行的,因此$0$1等不是填充在该部分。试试这个:

$ cat tst.awk
BEGIN{ OFS="\t" }
{
    if ($5 == gen) {
        fin = $3
    }
    else {
        prtGen()
        ch  = $1
        ini = $2
        gen = $5
    }
}
END { prtGen() }

function prtGen() {
    if (ini != "") {
        print ch, ini, fin, gen
    }
}
$
$ awk -f tst.awk file
chr1    3204563 3661429 Xkr4
chr1    4280927 4399268 Rp1
chr1    4481009 4486494 Sox17
chr1    4763279 4764597 Mrpl15

请注意,如果输入文件为空,则上述操作不会产生任何输出,这是您在文本处理脚本中始终需要的内容。

答案 2 :(得分:0)

不是对起始空行问题的回答,但是在这种情况下,如果输入文件是有序的,这种替代方法可能会很有趣:

awk '$NF!=p{print x}{p=$NF}1' file | awk '{print $1,$2,$(NF-2),$NF}' RS=

输出:

chr1 3204563 3661429 Xkr4
chr1 4280927 4399268 Rp1
chr1 4481009 4486494 Sox17
chr1 4763279 4764597 Mrpl15