Bash脚本在文本文件中读取随机行

时间:2014-11-03 15:46:48

标签: bash random

我有一个单行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

出现。我想知道它是否可以随机获得。

3 个答案:

答案 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)

你想要的东西显然不那么随意。

如果您不想重复旧行,则需要某种方法来记住之前的结果。

我要做的是将整个文件随机播放并存储在某个地方。 然后每次调用脚本时抓住最后一行并将其删除。 一旦你检测到文件是空的,你就必须再做一次洗牌。

如果您担心并发,则需要正确的文件锁定。