entropo
entropo

Reputation: 2481

Bash input from pipe

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

Upvotes: 3

Views: 6317

Answers (2)

Doon
Doon

Reputation: 20232

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

Upvotes: 1

Michał Šrajer
Michał Šrajer

Reputation: 31192

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.

Upvotes: 2

Related Questions