首页 > 解决方案 > 如果一列的值等于上一行中同一列的值加一,则给出相同的代码

问题描述

我有一些看起来像这样的数据:

chr1    3861154 N   20
chr1    3861155 N   20
chr1    3861156 N   20
chr1    3949989 N   22
chr1    3949990 N   22
chr1    3949991 N   22

我需要做的是根据第 2 列给出一个代码。如果该值等于前一行的值加一,那么它们来自同一个系列,我需要在新列中给它们相同的代码。该代码可能是该系列第一行的值。此示例的所需输出为:


chr1    3861154 N   20  3861154
chr1    3861155 N   20  3861154
chr1    3861156 N   20  3861154
chr1    3949989 N   22  3949989
chr1    3949990 N   22  3949989
chr1    3949991 N   22  3949989

我正在考虑使用 awk,但这当然不是必需的。关于如何使这项工作的任何想法?

编辑以添加我正在使用的代码:

awk 'BEGIN {var = $2} {if ($2 == var+1) print $0"\t"var; else print $0"\t"$2; var = $2 }' test

我认为这个想法是存在的,但还不完全正确。我得到的结果是:

chr1    3861154 N   20  3861154
chr1    3861155 N   20  3861154
chr1    3861156 N   20  3861155
chr1    3949989 N   22  3949989
chr1    3949990 N   22  3949989
chr1    3949991 N   22  3949990

谢谢!

标签: shellawk

解决方案


$ cat tst.awk
(NR == 1) || ($2 != (prev+1)) {
    val = $2
}
{
    print $0, val
    prev = $2
}

$ awk -f tst.awk file
chr1    3861154 N   20 3861154
chr1    3861155 N   20 3861154
chr1    3861156 N   20 3861154
chr1    3949989 N   22 3949989
chr1    3949990 N   22 3949989
chr1    3949991 N   22 3949989

您脚本中的大错误是这部分:

BEGIN {var = $2}

因为:

  • $2是当前输入行的第二个字段。
  • BEGIN在读取任何输入行之前执行。

因此$2,该BEGIN部分中的值是零或空,就像任何其他未设置的变量一样。


推荐阅读