Вы также можете использовать команду sort для получения случайной строки из файла.
sort -R filename | head -n1
Просто для удовольствия, вот чистое решение bash, которое не использует shuf, sort, wc, sed, head, tail или любые другие внешние инструменты. [!d0 ]
Единственным преимуществом по сравнению с вариантом shuf является то, что он немного быстрее, так как это чистый баш. На моей машине для файла из 1000 строк вариант shuf занимает около 0,1 секунды, а следующий сценарий занимает около 0,01 секунды;) Поэтому, когда shuf является самым простым и коротким вариантом, это происходит быстрее.
Честно говоря, я все равно поеду за решением shuf, если важна высокая эффективность.
#!/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"
Предположим, у вас есть файл notifications.txt. Нам нужно подсчитать общее количество строк, чтобы определить диапазон случайного генератора:
$ cat notifications.txt | wc -l
Давайте напишем переменную:
$ LINES=$(cat notifications.txt | wc -l)
Теперь, чтобы сгенерировать число от 0 до $LINE мы будем использовать переменную RANDOM.
$ echo $[ $RANDOM % LINES]
Давайте перепишем ее в переменную:
$ R_LINE=$(($RANDOM % LINES))
Теперь нам нужно только напечатать этот номер строки: [!d4 ]
$ sed -n "${R_LINE}p" notifications.txt
О RANDOM:
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.
Убедитесь, что ваш файл имеет менее 32767 номеров строк. См. Это, если вам нужен более крупный случайный генератор, который работает из коробки.
Пример:
$ od -A n -t d -N 3 /dev/urandom | tr -d ' '
Вот скрипт Python, который выбирает случайную строку из входных файлов или stdin:
#!/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
Алгоритм O (n) -time, O (1) -пространство. Он работает для файлов размером более 32767 строк. Он не загружает входные файлы в память. Он считывает каждую строку ввода ровно один раз, т. Е. Вы можете передать в нее произвольное большое (но конечное) содержимое. Вот объяснение алгоритма.
Меня впечатляет работа, которую Malte Skoruppa и другие сделали, но здесь намного проще использовать «чистый баш»:
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
Как некоторые отметили, $ RANDOM не случайным. Тем не менее, ограничение размера файла 32767 строк преодолевается путем наложения $ RANDOM вместе по мере необходимости.