AWK在满足条件时随机选择2个动作中的1个

时间:2019-03-20 18:34:08

标签: bash awk

在满足以下条件的情况下,我可以用文件中的另一个值代替一个值:

awk '{if (length($4)*2+1 != length($5) && $10 ~ /^1\/2/) sub("1/2","1/1"); print}' MyFile

在我的两个条件都为真的行中将“ 1/2”替换为“ 1/1”。

我的文件中有几种这样的情况,我真正想做的是在大约一半的情况下将“ 1/2”替换为“ 1/1”,而将“ 1/2”替换为“在大约另一半情况下为2/2“。也就是说,随机选择两个可能的动作sub("1/2","1/1")sub("1/2","2/2")之一。这有可能吗?

非常感谢!

3 个答案:

答案 0 :(得分:5)

awk '
    length($4)*2+1 != length($5) && $10 ~ /^1\/2/ {
        sub("1/2", rand() < 0.5 ? "1/1" : "2/2")
        print
    }
' MyFile

答案 1 :(得分:3)

每行调用rand()的问题是,最终所有sub()都相同。要保证大约一半可以做到:

awk '
    BEGIN { srand() }
    length($4)*2+1 != length($5) && $10 ~ /^1\/2/ {
        if ( ++cnt % 2 ) {
            dir = (rand() < 0.5 ? 1 : 0)
        }
        else {
            dir = !dir
        }
        sub("1/2", (dir ? "1/1" : "2/2"))
    }
    { print }
' MyFile

但是它的随机性要低一些,因为每第二行都与前一行相反。

答案 2 :(得分:1)

这是动态调整阈值以产生更平衡分布的另一种方法。

awk 'BEGIN {srand()}
     length($4)*2+1 != length($5) && $10 ~ /^1\/2/ {
          r=rand()<(1-(c1+1)/(c+2)); 
          c1+=r; c++;
          sub("1/2", r?"1/1":"2/2")}1' file

偶然地假设前三个r值为1,第四个r更有可能为0(1的概率为1-4 / 5 = 0.2而不是0.5)。这仍然不能给您准确的一半和一半的分裂。为此,更容易预先计算出确切的数字并使用shuf

也许也仅将sub限制为$10吗?