Как отобразить случайную строку от текстового файла?

Я пытаюсь записать сценарий оболочки. Идея состоит в том, чтобы выбрать одну строку наугад из текстового файла и отобразить его как настольное уведомление Ubuntu.

Но я хочу, чтобы различные строки были выбраны каждый раз, когда я выполняю сценарий. Там какое-либо решение состоит в том, чтобы сделать это? Я не хочу весь сценарий. Просто та простая вещь только.

25
задан 19 September 2014 в 02:35

6 ответов

Можно использовать shuf утилита для печати случайных строк из файла

$ shuf -n 1 filename

-n: количество строк для печати

Примеры:

$ shuf -n 1 /etc/passwd

git:x:998:998:git daemon user:/:/bin/bash

$ shuf -n 2 /etc/passwd

avahi:x:84:84:avahi:/:/bin/false
daemon:x:2:2:daemon:/sbin:/bin/false
38
ответ дан 16 November 2019 в 11:53

Можно также использовать sort команда для получения случайной строки из файла.

sort -R filename | head -n1
13
ответ дан 16 November 2019 в 11:53

Только для забавы, вот чистое решение для удара, которое не использует shuf, sort, wc, sed, head, tail или никакие другие внешние инструменты.

единственное преимущество перед shuf вариант - то, что это немного быстрее, так как это - чистый удар. На моей машине для файла 1 000 строк 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"
8
ответ дан 16 November 2019 в 11:53

Скажите, что у Вас есть файл notifications.txt. Мы должны считать общее количество строк, для определения диапазона случайного генератора:

$ cat notifications.txt | wc -l

Позволяет записи к переменной:

$ LINES=$(cat notifications.txt | wc -l)

Теперь для генерации числа от 0 до $LINE мы будем использовать RANDOM переменная.

$ echo $[ $RANDOM % LINES]

Позволяет, пишут его в переменную:

$  R_LINE=$(($RANDOM % LINES))

Теперь мы только должны распечатать этот номер строки:

$ sed -n "${R_LINE}p" notifications.txt
<час>

О СЛУЧАЙНОМ:

   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.

Быть уверенным Ваш файл имеют менее тогда 32 767 номеров строки. См. это при необходимости в более крупном случайном генераторе, который работает из поля.

Пример:

$ od -A n -t d -N 3 /dev/urandom | tr -d ' '
4
ответ дан 16 November 2019 в 11:53

Вот сценарий 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) разовый, O (1) - пространство. Это работает на файлы, больше, чем 32 767 строк. Это не загружает входные файлы в память. Это читает каждую входную строку точно однажды, т.е. можно передать по каналу произвольный большой (но конечный) содержание в него. Вот объяснение алгоритма .

2
ответ дан 16 November 2019 в 11:53

Я впечатлен работой, которую Malte Skoruppa и другие сделали, но здесь являются намного более простым "чистым ударом" способ сделать это:

IFS= 

, Поскольку некоторые отметили, $RANDOM не случаен. Однако предел размера файла 32 767 строк преодолен путем строкового представления $RANDOMs вместе по мере необходимости.

\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 не случаен. Однако предел размера файла 32 767 строк преодолен путем строкового представления $RANDOMs вместе по мере необходимости.

1
ответ дан 16 November 2019 в 11:53

Другие вопросы по тегам:

Похожие вопросы: