3

I wrote a trivial bash script which dumps a random line from a file or STDIN:

#!/bin/bash
if [ $# -ne 1 ]
then
    echo "Syntax: $0 FILE (or \'-\' for STDIN)"
    echo $0 - display a random line from FILE
    exit 1
fi

RAND=`cat /proc/sys/kernel/random/uuid | cut -c1-4 | od -d | head -1 | cut -d' ' -f2`

if [ $1 != "-" ]
then
    LINES=`cat "$1" | wc -l`
    LINE=`expr $RAND % $LINES + 1`
    head -$LINE $1 | tail -1
else
    piped=`cat -`
    LINES=`echo "$piped" | wc -l`
    LINE=`expr $RAND % $LINES + 1`
    echo "$piped" | head -$LINE | tail -1
fi

However, I'd like it to also process STDIN if there are no options passed (but still fail with the help if there's no STDIN from a pipe).

That is, I'd like to say:

echo "foo\nbar\nbaz" | randline

... instead of ...

echo "foo\n\bar\nbaz" | randline -

How can this be done?

Edit:
Thanks to Doon!

#!/bin/bash
if [ "$( tty )" == 'not a tty' ]
then
    STDIN_DATA_PRESENT=1
else
    STDIN_DATA_PRESENT=0
fi

if [[ $# -ne 1 && $STDIN_DATA_PRESENT -eq 0 ]]
then
    echo "Syntax: $0 [FILE (or \'-\' for STDIN)]"
    echo $0 - display a random line from FILE
    echo -e "\nWill also process piped STDIN if no arguments are given."
    exit 1
fi

RAND=`cat /proc/sys/kernel/random/uuid | cut -c1-4 | od -d | head -1 | cut -d' ' -f2`

if [[ $1 && $1 != "-" ]]
then
    LINES=`cat "$1" | wc -l`
    LINE=`expr $RAND % $LINES + 1`
    head -$LINE $1 | tail -1
else
    piped=`cat -`
    LINES=`echo "$piped" | wc -l`
    LINE=`expr $RAND % $LINES + 1`
    echo "$piped" | head -$LINE | tail -1
fi
oers
  • 18,436
  • 13
  • 66
  • 75
entropo
  • 2,481
  • 15
  • 15
  • 1
    see here http://stackoverflow.com/questions/635361/ksh-how-to-probe-stdin it is for ksh, but an answer for bash is provided – Doon Apr 19 '11 at 02:42
  • 1
    You should remove the solution from your question and add it as an answer (and accept it if it actually solved your problem). – murgatroid99 Sep 19 '11 at 02:04

2 Answers2

2

To get random line from a file you can do:

awk 'BEGIN{srand();}{printf "%04d %s\n", int(rand()*10000), $0}' < $FILENAME | sort | cut -f2- -d' ' | head -1

Here we do:

  1. add random number to the beginning of each line
  2. sort output
  3. remove random number from the beginning of each line
  4. print first line (of mixed output)

BTW, in if you are using BASH, you can use $RANDOM (provided by bash) variable instead of generating $RAND by your self.

Michał Šrajer
  • 30,364
  • 7
  • 62
  • 85
1

see here ksh: how to probe stdin? it is for ksh, but an answer for bash is provided

Community
  • 1
  • 1
Doon
  • 19,719
  • 3
  • 40
  • 44