代码之家  ›  专栏  ›  技术社区  ›  FatihSarigol

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

  •  0
  • FatihSarigol  · 技术社区  · 6 年前

    当满足以下条件时,我可以用文件中的另一个值替换值:

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

    在我的档案中有几个这样的案例,我真正想做的是在大约一半的案例中用“1/1”替换“1/2”,而在另外一半的案例中,用“2/2”代替“1/2”。也就是说,从2个可能的动作中随机选择一个 sub("1/2","1/1") sub("1/2","2/2") . 这有可能吗?

    非常感谢!

    0 回复  |  直到 6 年前
        1
  •  3
  •   Ed Morton    6 年前

    对每一行调用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
  •  5
  •   glenn jackman    6 年前
    awk '
        length($4)*2+1 != length($5) && $10 ~ /^1\/2/ {
            sub("1/2", rand() < 0.5 ? "1/1" : "2/2")
            print
        }
    ' MyFile
    
        3
  •  1
  •   karakfa    6 年前

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

    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
    

    假设第一个3r值是1,第四个r值更可能是0(1的概率是1-4/5=0.2,而不是0.5)。这仍然不能给你准确的一分为二。为此,更容易有准确的计数和使用 shuf

    或许也限制了 sub $10