rand: --fmt FORMAT implemented.

This commit is contained in:
Ole Tange 2020-03-17 02:23:09 +01:00
parent 93436e3511
commit 0047319b1b

View file

@ -10,7 +10,7 @@ rand - generate (pseudo-)random data
=head1 SYNOPSIS =head1 SYNOPSIS
B<rand> [[I<from>] I<to>] B<rand> [-f FORMAT|--format FORMAT] [[I<from>] I<to>]
=head1 DESCRIPTION =head1 DESCRIPTION
@ -27,6 +27,19 @@ If I<to> is given, numbers will be integers from 0 to I<to>.
If I<from> is also given, numbers will be integers from I<from> to I<to>. If I<from> is also given, numbers will be integers from I<from> to I<to>.
=head1 OPTIONS
=over 4
=item B<--format> I<FORMAT>
=item B<-f> I<FORMAT>
Format number using I<FORMAT>. I<FORMAT> follows B<printf>s specification.
=back
=head1 EXAMPLE =head1 EXAMPLE
Overwrite a harddisk with random data: Overwrite a harddisk with random data:
@ -41,9 +54,16 @@ Overwrite a harddisk with random data:
rand 1000 1999 | head -n 100 rand 1000 1999 | head -n 100
=head1 EXAMPLE
100 random numbers from 256 to 65535 in hex with 0s prepended:
rand -f '%04x\n' 256 65535 | head -n 100
=head1 AUTHOR =head1 AUTHOR
Copyright (C) 2017 Ole Tange, Copyright (C) 2017-2020 Ole Tange,
http://ole.tange.dk and Free Software Foundation, Inc. http://ole.tange.dk and Free Software Foundation, Inc.
@ -67,7 +87,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
=head1 DEPENDENCIES =head1 DEPENDENCIES
B<rand> uses B<openssl>. B<rand> uses B<openssl>, B<perl>, and B<parallel>.
=head1 SEE ALSO =head1 SEE ALSO
@ -77,42 +97,58 @@ B<openssl>
=cut =cut
# Generate random 8-bit data by AES encrypting /dev/zero with a random randdata() {
# key # Generate random 8-bit data by AES encrypting /dev/zero with a
randfunc() { # random key
key=$(openssl rand -hex 16) key=$(openssl rand -hex 16)
iv=$(openssl rand -hex 16) iv=$(openssl rand -hex 16)
< /dev/zero openssl enc -aes-128-ctr -K $key -iv $iv 2>/dev/null < /dev/zero openssl enc -aes-128-ctr -K $key -iv $iv 2>/dev/null
} }
export -f randfunc export -f randdata
ints() { ints() {
# Convert random data on stdin to numbers $from..$to in $fmt
from=$1 from=$1
to=$2 to=$2
fmt="$3"
# Allow up to 2^64 # Allow up to 2^64
perl -e '$diff='$to-$from'+1; perl -e '$diff='$to-$from'+1;
$factor = 2**64/$diff; $factor = 2**64/$diff;
while(sysread(STDIN,$buf,65536)) { while(sysread(STDIN,$buf,65536)) {
print map { (int($_ / $factor) + '$from'),"\n" } unpack("Q*",$buf); print map { sprintf("'"$fmt"'", int($_ / $factor) + '$from'); } unpack("Q*",$buf);
}' }'
} }
export -f ints export -f ints
randints() { randints() {
randfunc | ints "$@" randdata | ints "$@"
} }
export -f randints export -f randints
# Default format of ints
fmt='%s\n'
while true; do
case "$1" in
-f | --fmt ) fmt="$2"; shift 2 ;;
-D | --debug ) debug=true; shift ;;
-h | --help ) help=1; shift 2 ;;
-- ) shift; break ;;
* ) break ;;
esac
done
qfmt="$(parallel --shellquote --shellquote ::: "$fmt")"
if [ "$1" == "" ] ; then if [ "$1" == "" ] ; then
# Boost performance by running 1 per CPU core # Boost performance by running 1 per CPU core
eval parallel -u randfunc ::: {1..$(parallel --number-of-cores)} eval parallel -u randdata ::: {1..$(parallel --number-of-threads)}
else else
# $1 set => numerical # $1 set => numerical
if [ "$2" == "" ] ; then if [ "$2" == "" ] ; then
# 0 .. $1 # 0 .. $1
eval parallel --lb randints 0 $1 ::: {1..$(parallel --number-of-cores)} eval parallel -N0 --lb randints 0 $1 "$qfmt" ::: {1..$(parallel --number-of-threads)}
else else
# $1 .. $2 # $1 .. $2
eval parallel --lb randints $1 $2 ::: {1..$(parallel --number-of-cores)} eval parallel -N0 --lb randints $1 $2 "$qfmt" ::: {1..$(parallel --number-of-threads)}
fi fi
fi fi