我有一个单行bash脚本,可以读取文本文件中的随机行:
#!/bin/bash
shuf -n 1 excuses.txt
当我调用脚本时,它给了我一个随机的单行,但我注意到我在脚本中使用的命令实际上并非完全随机,当我多次运行脚本时,我可能会看到同一行被读取(即使它是随机的)。我的问题是:是否有另一种方法可以随机打印一行文本,这些文本可能比我在代码中的内容更随机?请注意,我有1000行可以从这个文本文件中读取。
编辑:以下是我使用shuf
随机化文本文件时的结果:
[root@ftpserver bofh] ./bastardScript.sh
Atilla the Hub
[root@ftpserver bofh] ./bastardScript.sh
kernel panic: write-only-memory (/dev/wom0) capacity exceeded.
[root@ftpserver bofh] ./bastardScript.sh
We had to turn off that service to comply with the CDA Bill.
[root@ftpserver bofh] ./bastardScript.sh
YOU HAVE AN I/O ERROR -> Incompetent Operator error
[root@ftpserver bofh] ./bastardScript.sh
Change in Earth's rotational speed
[root@ftpserver bofh] ./bastardScript.sh
Atilla the Hub
因此,您可以在我使用脚本的时间内看到(约6-10次):
[root@ftpserver bofh] ./bastardScript.sh
Atilla the Hub
出现。我想知道它是否可以随机获得。
答案 0 :(得分:2)
#!/bin/bash
cat excuses.txt | sort --random-sort | head -n 1
答案 1 :(得分:2)
如果您想确保shuf
使用高熵源:
shuf -n 1 --random-source=/dev/random <excuses.txt
那就是说,你真正想要的是两次看不出同样的借口(直到他们都被消费了)。在这种情况下,我会考虑将文件洗牌一次,存储一个计数器,并依次显示每一行。
# In Bash 3 or earlier, you'll need to hardcode a FD number here.
exec {lock_fd}>excuses.count
flock -x "$lock_fd"
[[ -e excuses.shuffled ]] || {
shuf <excuses.txt >excuses.shuffled || exit
echo 1 >excuses.count
}
[[ -s excuses.shuffled ]] || exit
counter=$(<excuses.count)
line=$(sed -n "${counter} p" <excuses.shuffled)
if [[ $line ]]; then
echo "$line"
echo "$((counter + 1))" >excuses.count
else
# ran out of lines; delete files and restart this script to reshuffle
rm -- excuses.shuffled # clear our now-used shuffle
exec {lock_fd}<&- # release the lock
exec "$0" "$@" # restart the script
fi
答案 2 :(得分:1)
你想要的东西显然不那么随意。
如果您不想重复旧行,则需要某种方法来记住之前的结果。
我要做的是将整个文件随机播放并存储在某个地方。 然后每次调用脚本时抓住最后一行并将其删除。 一旦你检测到文件是空的,你就必须再做一次洗牌。
如果您担心并发,则需要正确的文件锁定。