awk之随机函数rand()和srand() (转)
文件:
1234567
abcdefg
......
现在想要随机抽取5列组成下面的内容,允许重复:
36612
cffab
......
1 awk -F '' 'BEGIN{srand();for(i=1;i<=5;i++)a[i]=int(rand()*100%7+1)}{for(i=1;i<=5;i++)printf $a[i];printf RS}' file
[解析]
思路是首先把FS设置为空,随机抽取5列,那么在BEGIN模块定义数组a中1~5的下标对应随机的1~7的值,在读行时把数组a的值(这是个1~7的随机值)作为字段打印出来,这样就实现了随机抽取7个字段中的5个字段重新组成新的行。
rand()函数是随机产生一个0到1之间的保留小数点后6位的小数值,例如0.217788,所以需要乘以100得到21.7788,然后再对7取余,结果是0.7788,int()取整是0了,我们要获得1~7的随机数,所以加1,整个表达式才是 int(rand()*100%7+1) ,其实 int(length*rand()+1) 也是可以得到1~7的随机数的,只是在BEGIN中,length函数还是为0,这样就得到了肯定产生于1~7之间的随机数,问题在于rand()只产生一次,怎么让它滚动起来呢?这里我们还需要srand()函数,括号内没有表达式的话,它会采用当前时间作为随机计数器的种子,这样以秒为间隔,随机数
计数器的种子,这样以秒为间隔,随机数就能滚动随机生成了。最后再对应数组a的随机值作为字段打印出来。
1 #!/bin/bash 2 len="5" 3 while read line; do 4 str="" 5 while [ "${#str}" -lt "$len" ]; do 6 letter="${line:$(($RANDOM%${#line})):1}" 7 str="$str$letter" 8 done 9 echo $str 10 done < file
[解析]
同样,这个shell脚本也能实现该功能,首先定义变量 len=5 ,因为只需要5列嘛。然后从file文件中读入一行内容给变量 line ,定义一个长度为0的变量 str ,当 str 变量长度大于等于5了,就不再会继续whlie循环,然后打印该变量,在bash中 ${#var} 就是获取变量的长度,我们再看看怎么实现的随机,该shell的原理是读取 line 变量的随机0~6位置长度为1的字符,环境变量RANDOM,范围是0~32767,RANDOM对7取余的结果是0~6,就能随机抽取长度为7的字符串中的任意一个字符,然后把该字符累计给变量 str ,满足长度5后就打印出该行。
谢谢Tim和shell_HAT的精彩代码。
----------------------------------------------------------------------------------
数据和特征决定了效果上限,模型和算法决定了逼近这个上限的程度
----------------------------------------------------------------------------------