Bash Script to Make a Random Selection of Lines in a File

in #bash2 years ago (edited)

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.

Sort:  

!trendovoter 100

Thanks

Hello @droida

Thank you for following @haccolong account. As a follower of @haccolong this post has been randomly selected and upvoted by @hoaithu's Curation Trail.

To earn more rewards with your Steemit account. Check through some of the ways at this post.

I will continue with random upvotes in the future & wish you lots of luck. :)

You got voted by @curationkiwi thanks to droida! This bot is managed by KiwiJuce3 and run by Rishi556, you can check both of them out there. To receive upvotes on your own posts, you need to join the Kiwi Co. Discord and go to the room named #CurationKiwi. Submit your post there using the command "!upvote (post link)" to receive upvotes on your post. CurationKiwi is currently supported by donations from users like you, so feel free to leave an upvote on our posts or comments to support us!
We have also recently added a new whitelist feature for those who would like to support CurationKiwi even more! If you would like to receive upvotes more than 2x greater than the normal upvote, all you need to do is delegate 50 SP to @CurationKiwi using this link.

This post has received a 3.13 % upvote from @drotto thanks to: @curationkiwi.

This post has received a 100.0 % upvote from @boomerang.

You got a 10.00% upvote from @minnowvotes courtesy of @droida!

Congratulations @theguruasia, 100% upvote has been shared with your successful call on the post that shared by @droida!


Support @trendotoken projects by delegating : 100SP , 200SP , 500SP , 1000SP , 2000SP