AWK - 在指定数量的随机行中替换为常量字符

时间:2015-03-09 21:48:59

标签: bash awk

我的任务是修改蒙面基因型,我必须掩盖(隐藏)2%的基因型。

我这样做的文件看起来像这样(genotype.dat):

M rs4911642
M rs9604821
M rs9605903
M rs5746647
M rs5747968
M rs5747999
M rs2070501
M rs11089263
M rs2096537

并掩饰它,我只需将M改为S2。

然而,我必须对5505行中的110(2%)执行此操作,因此我使用随机数生成器的策略(在1到5505之间生成110个数字,然后手动更改相应的行号' s M到S2花了差不多一个小时......(我知道,并不是非常复杂)。

我考虑将数字保存在一个单独的文件(maskedlines.txt)中,然后告诉awk用S2替换该行号中的第一个字符,但我找不到任何可调节的例子来执行此操作。

无论如何,任何有关如何解决这个问题的建议都将深受赞赏。

2 个答案:

答案 0 :(得分:1)

awk 'NR==FNR{a[$1]=1;next;} a[FNR]{$1="S2"} 1' maskedlines.txt genotype.dat

如何运作

总而言之,我们首先将maskedlines.txt读入关联数组a。假设该文件每行有一个数字,并且该数字的a设置为1。然后我们读入genotype.dat。如果该行号的a为1,我们会将第一个字段更改为S2以屏蔽它。然后打印该行,无论是否改变。

详细说明:

  • NR==FNR{a[$1]=1;next;}

    在awk中,FNR是到目前为止从当前文件读取的记录(行)数,NR是到目前为止读取的总行数。所以,当NR==FNR时,我们正在读取第一个文件(maskedlines.txt)。此文件包含要屏蔽的genotype.dat中的行号。对于这些行号中的每一行,我们将a设置为1.然后我们跳过其余命令并跳转到next行。

  • a[FNR]{$1="S2"}

    如果我们到这里,我们正在处理第二个文件:genotype.dat。对于此文件中的每一行,我们会检查FNR中是否提及其行号maskedlines.txt。如果是,我们将第一个字段设置为S2以掩盖此行。

  • 1

    这是打印当前行的awck简洁速记。

答案 1 :(得分:1)

这是一个简单的方法,如果你有shuf(它在Gnu coreutils中,所以如果你有Linux,你几乎肯定有它):

sed "$(printf '%ds/M/S2/;' $(shuf -n110 -i1-5505 | sort -n))" \
    genotype.dat > genotype.masked

更复杂的版本不依赖于知道你想要掩盖5505行中的110行;您可以使用lines=$(wc -l < genotype.dat)轻松提取行数,然后从中计算百分比。

shuf用于生成随机的行样本,通常来自文件; -i1-5505选项意味着使用1到5505之间的整数,-n110表示生成110的随机样本(不重复)。在使用printf创建sed编辑脚本之前,我对其效率进行了排序。