#!/bin/bash
FILE=file.txt
# get line count for $FILE (simulate 'wc -l')
lc=0
while read -r line; do
((lc++))
done < $FILE
# get a random number between 1 and $lc
rnd=$RANDOM
let "rnd %= $lc"
((rnd++))
# traverse file and find line number $rnd
i=0
while read -r line; do
((i++))
[ $i -eq $rnd ] && break
done < $FILE
# output random line
printf '%s\n' "$line"
RANDOM Each time this parameter is referenced, a random integer between
0 and 32767 is generated. The sequence of random numbers may be
initialized by assigning a value to RANDOM. If RANDOM is unset,
it loses its special properties, even if it is subsequently
reset.
#!/usr/bin/env python
"""Usage: select-random [<file>]..."""
import random
def select_random(iterable, default=None, random=random):
"""Select a random element from iterable.
Return default if iterable is empty.
If iterable is a sequence then random.choice() is used for efficiency instead.
If iterable is an iterator; it is exhausted.
O(n)-time, O(1)-space algorithm.
"""
try:
return random.choice(iterable) # O(1) time and space
except IndexError: # empty sequence
return default
except TypeError: # not a sequence
return select_random_it(iter(iterable), default, random.randrange)
def select_random_it(iterator, default=None, randrange=random.randrange):
"""Return a random element from iterator.
Return default if iterator is empty.
iterator is exhausted.
O(n)-time, O(1)-space algorithm.
"""
# from https://stackoverflow.com/a/1456750/4279
# select 1st item with probability 100% (if input is one item, return it)
# select 2nd item with probability 50% (or 50% the selection stays the 1st)
# select 3rd item with probability 33.(3)%
# select nth item with probability 1/n
selection = default
for i, item in enumerate(iterator, start=1):
if randrange(i) == 0: # random [0..i)
selection = item
return selection
if __name__ == "__main__":
import fileinput
import sys
random_line = select_random_it(fileinput.input(), '\n')
sys.stdout.write(random_line)
if not random_line.endswith('\n'):
sys.stdout.write('\n') # always append newline at the end
IFS=$'\012'
# set field separator to newline only
lines=( $(<test5) )
# slurp entire file into an array
numlines=${#lines[@]}
# count the array elements
num=$(( $RANDOM$RANDOM$RANDOM % numlines ))
# get a (more-or-less) random number within the correct range
line=${lines[$num]}
# select the element corresponding to the random number
echo $line
# display it
您可以使用
shuf
实用程序从文件中打印随机行-n
: 要打印的行数例子:
您还可以使用
sort
命令从文件中获取随机行。只是为了好玩,这是一个不使用、、、、或任何其他外部工具的纯 bash 解决方案。
shuf
sort
wc
sed
head
tail
与该变体相比的唯一优势
shuf
是它稍微快一些,因为它是纯 bash。在我的机器上,对于一个 1000 行的文件,shuf
变体大约需要 0.1 秒,而下面的脚本大约需要 0.01 秒 ;) 所以虽然shuf
这是最简单和最短的变体,但速度更快。shuf
老实说,除非高效率是一个重要问题,否则我仍然会寻求解决方案。假设你有 file
notifications.txt
。我们需要计算总行数,以确定随机生成器的范围:让我们写入变量:
现在要从到生成数字
0
,$LINE
我们将使用RANDOM
变量。让我们将它写入变量:
现在我们只需要打印这个行号:
关于随机:
确保您的文件的行号少于 32767。如果您需要开箱即用的更大的随机生成器,请参阅此内容。
例子:
这是一个从输入文件或标准输入中选择随机行的 Python 脚本:
该算法是 O(n)-时间,O(1)-空间。它适用于大于 32767 行的文件。它不会将输入文件加载到内存中。它只读取每个输入行一次,即,您可以将任意大(但有限)的内容通过管道传输到其中。这是算法的解释。
Malte Skoruppa 和其他人所做的工作给我留下了深刻的印象,但这里有一种更简单的“纯 bash”方法:
正如一些人指出的那样,$RANDOM 不是随机的。但是,根据需要将 $RANDOM 串在一起可以克服 32767 行的文件大小限制。