randomlines.sh [--verbose] <FILE> <COUNT>
Prints COUNT lines from FILE randomly
Usecases
You have a list of cities you wish to travel to during your summer holidays but you don't know which ones to visit first. This program for Linux, randomlines.sh can help you to decide where to go first. It also could be used to randomly elect steemians or posts for a contest.
Format the Data
Put the list in a file. One item, one line.
towns.csv
Amsterdam
Athens
...
Stockholm
Vienna
The command
To know the 5 next cities to travel to, just type the command in a terminal:
$ ./randomlines.sh towns.csv 5
It produces the output:
Paris
Vienna
Geneva
Monaco
Athens
Verbose Option
Unfortunately, it doesn't post the result in the blockchain yet ;)
$ ./randomlines.sh --verbose towns.csv 5
towns.csv has 16 lines
Drawing 5 numbers between 1 and 16
Numbers: 12 3 6 10 16
#12 Paris
#3 Barcelona
#6 Brussels
#10 Monaco
#16 Vienna
The source code
I'm lazy, nevertheless I added comments.
#!/bin/bash
# function to print a random number between $1 and $2
randint() {
min=$1
max=$2
# modulo
let "mod=1+max-min"
# big random hex number (16 hex numbers, uppercase)
h=$(openssl rand -hex 16 | tr [a-z] [A-Z])
# decimal conversion
n=$(echo "ibase=16; $h" | bc)
# print the random number
echo "($n % $mod) + $min" | bc
}
# parameters
if [[ "$1" == "--verbose" ]] ; then
verbose=0 # true
shift
fi
file=$1
todraw=$2
# checks
if [[ "$todraw" == "" ]] ; then
echo "Usage $0 [--verbose] <FILE> <COUNT>";
exit 1
fi
if [ ! -e "$file" ] ; then
echo "File $file does not exist"
exit 1
fi
# limits
min=1
max=$(wc -l $file | cut -d\ -f1)
if [ $verbose ] ; then echo "$file has $max lines" ; fi
if [[ "$todraw" -gt "$max" ]] ; then
echo "File $file has too few lines ($max) to draw $todraw distinct items"
exit 1
fi
# draw distinct random numbers
if [ $verbose ] ; then echo "Drawing $todraw numbers between $min and $max" ; fi
count=0
numbers=""
while [[ "$count" != "$todraw" ]] ; do
value=$(randint $min $max)
found=$(echo $numbers | egrep "^$value | $value | $value$")
if [[ "$found" == "" ]] ; then
numbers="$numbers $value"
let "count=count+1"
fi
done
if [ $verbose ] ; then echo "Numbers: $numbers" ; fi
# print elected lines
for number in $numbers ; do
if [ $verbose ] ; then echo -n "#$number " ; fi
# print the corresponding line of the file
sed -n "$number"p $file
done
exit 0
I hope you'll find it useful. Questions, suggestions and remarks are welcome.