シェルスクリプトを記述しようとしています。アイデアは、テキストファイルからランダムに1行を選択し、Ubuntuデスクトップ通知として表示することです。
ただし、スクリプトを実行するたびに異なる行を選択する必要があります。これを行う解決策はありますか?スクリプト全体は必要ありません。単純なことだけです。
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
sort
コマンドを使用して、ファイルからランダムな行を取得することもできます。
sort -R filename | head -n1
ファイル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について:
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未満であることを確認してください。箱から出して動作するより大きなランダムジェネレータが必要な場合は、 this を参照してください。
例:
$ od -A n -t d -N 3 /dev/urandom | tr -d ' '
入力ファイルまたは標準入力からランダムな行を選択するPythonスクリプトは次のとおりです。
#!/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 __== "__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)スペースです。 32767行を超えるファイルに対して機能します。入力ファイルをメモリにロードしません。各入力行を1回だけ読み取ります。つまり、任意の大きな(ただし有限の)コンテンツをそこにパイプできます。 アルゴリズムの説明 です。
Malte Skoruppaなどが行った作業には感心しましたが、ここではそれを行うためのはるかに単純な「純粋なbash」方法を示します。
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を連結することで克服されます。