如何在Bash中N次执行命令1次


15

我想要一种随机运行命令的方法,每10次说1次。是否有内置的或GNU coreutil来执行此操作,理想情况是:

chance 10 && do_stuff

do_stuff十次执行一次?我知道我可以编写脚本,但这似乎很简单,我想知道是否有定义的方法。


1
这是一个相当不错的指标,表明您的脚本可能已经变得一发不可收拾,以至于bash继续成为合理的选择。您应该考虑使用更完善的编程语言,也许是像Python或Ruby这样的脚本语言。
亚历山大-恢复莫妮卡

@Alexander这甚至不是一个真正的脚本,只有一行。我在cron作业中使用它来
不时

Answers:


40

ksh,Bash,Zsh,Yash或BusyBox中sh

[ "$RANDOM" -lt 3277 ] && do_stuff

RANDOM每次对其进行评估时,Korn,Bash,Yash,Z和BusyBox外壳程序的特殊变量都会生成一个介于0到32767之间的伪随机十进制整数值,因此上面给出的机会(接近)为十分之一。

您可以使用它来产生一个函数,该函数的行为至少在Bash中如您所描述的那样:

function chance {
  [[ -z $1 || $1 -le 0 ]] && return 1
  [[ $RANDOM -lt $((32767 / $1 + 1)) ]]
}

忘记提供参数或提供无效参数将产生1的结果,因此chance && do_stuff永远不会do_stuff

这使用的通用公式“ n中的 1 ” $RANDOM,即在32768中[[ $RANDOM -lt $((32767 / n + 1)) ]]获得(⎣32767/ n / + 1)的机会。其值n不是32768的因数,因为可能值范围内的不均匀分割而引入了偏差。


(1/2)关于此问题:直观地,零件数应该有上限,例如,不能有40.000零件。实际上,实际限制要小得多。问题在于整数除法只是每个部分的大小的近似值。要求两个连续的零件导致极限的差异$((32767/parts+1))大于1,否则我们会面临零件数量增加1的风险,而相除的结果(因此极限)相同。(续)
Isaac

(2/2)(续)。这将占比实际可用数量更多的数字。公式为(32767/n-32767/(n+1))>=1,求解n给出约181.5的极限。实际上,零件数量最多可以达到194个。但是在195份时,结果极限为151,与194份时相同。那是不一致的,应该避免。简而言之,零件数量(n)的上限应为194。您可以进行极限测试:[[ -z $1 || $1 -le 1 || $1 -ge 194 ]] && return 1
Isaac

25

非标解决方案:

[ $(date +%1N) == 1 ] && do_stuff

检查当前时间的最后一位(以纳秒为单位)是否为1!


棒极了。
埃里克·杜米尼尔

2
您必须确保通话[ $(date +%1N) == 1 ] && do_stuff不会定期进行,否则会破坏随机性。认为while true; do [ $(date +1%N) == 1 ] && sleep 1; done是一个抽象的反例。但是,玩纳秒级的想法真的很好,我想我会用它,因此+1
XavierStuvw

3
@XavierStuvw如果代码正在检查秒数,我想您会明白一点。但是纳秒?它应该看起来确实是随机的。
Eric Duminil

9
@EricDuminil:不幸的是:1)合同未规定系统时钟必须提供实际的纳秒分辨率(它可能舍入到最接近的整数clock_getres()),2)禁止调度程序,例如,始终在100纳秒边界上启动时间片(即使时钟正确,也会引入偏差)。3)(通常)从中读取/dev/urandom或检查的值是获得随机值的受支持方法$RANDOM
凯文(Kevin)

1
@Kevin:非常感谢您的评论。
埃里克·杜米尼尔

21

使用的替代方法$RANDOMshuf命令:

[[ $(shuf -i 1-10 -n 1) == 1 ]] && do_stuff

会做的工作。对于从文件中随机选择行也很有用,例如 音乐播放列表。


1
不知道该命令。非常好!
Eisenknurr

12

改善第一个答案,并使您要实现的目标更加明显:

[ $(( $RANDOM % 10 )) == 0 ] && echo "You win" || echo "You lose"

1
$RANDOM % 10会产生偏差,除非$RANDOM产生正好是10个不同值的倍数(通常在二进制计算机中不会发生)
phuclv

1
@phuclv是的,它将具有与相同的偏差"$RANDOM" -lt $((32767 / n + 1))
Eisenknurr

是的,偏差是相同的,即十分之一为0.100006104,而不是0.1(当检查为0时)。
斯蒂芬·基特

1

我不确定是否要随机性或周期性...对于周期性:

for i in `seq 1 10 100`; do echo $i;done
1
11
21
31
41
51
61
71
81
91

您可以将其与上面的“ $ RANDOM”技巧混合使用,以产生更混乱的内容,例如:

因为我在seq 1 1000 $RANDOM; 做回声$ i;完成

HTH :-)

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.