Importing usr.bin/shuffle
This commit is contained in:
parent
b1e0ada171
commit
3d257f8073
6 changed files with 336 additions and 1 deletions
|
@ -410,6 +410,7 @@
|
|||
./usr/bin/seq minix-sys
|
||||
./usr/bin/sha1 minix-sys
|
||||
./usr/bin/shar minix-sys
|
||||
./usr/bin/shuffle minix-sys
|
||||
./usr/bin/shutdown minix-sys
|
||||
./usr/bin/sleep minix-sys
|
||||
./usr/bin/slip minix-sys
|
||||
|
@ -1396,6 +1397,7 @@
|
|||
./usr/man/man1/sha1.1 minix-sys
|
||||
./usr/man/man1/shar.1 minix-sys
|
||||
./usr/man/man1/shift.1 minix-sys
|
||||
./usr/man/man1/shuffle.1 minix-sys
|
||||
./usr/man/man1/sleep.1 minix-sys
|
||||
./usr/man/man1/sort.1 minix-sys
|
||||
./usr/man/man1/spell.1 minix-sys
|
||||
|
|
|
@ -162,6 +162,7 @@
|
|||
2012/10/17 12:00:00,usr.bin/printf
|
||||
2010/02/19 16:35:27,usr.bin/sed
|
||||
2010/05/27 08:40:19,usr.bin/seq
|
||||
2013/06/02 12:00:00,usr.bin/shuffle
|
||||
2012/10/17 12:00:00,usr.bin/sort
|
||||
2011/01/15 22:54:10,usr.bin/stat
|
||||
2012/02/10 16:16:12,usr.bin/su
|
||||
|
|
|
@ -23,7 +23,7 @@ SUBDIR= \
|
|||
printf \
|
||||
\
|
||||
\
|
||||
sed seq \
|
||||
shuffle sed seq \
|
||||
sort stat su \
|
||||
tic tput \
|
||||
tsort \
|
||||
|
|
8
usr.bin/shuffle/Makefile
Normal file
8
usr.bin/shuffle/Makefile
Normal file
|
@ -0,0 +1,8 @@
|
|||
# $NetBSD: Makefile,v 1.2 2006/08/26 18:17:43 christos Exp $
|
||||
|
||||
PROG= shuffle
|
||||
|
||||
LDADD+=-lutil
|
||||
DPADD+=${LIBUTIL}
|
||||
|
||||
.include <bsd.prog.mk>
|
104
usr.bin/shuffle/shuffle.1
Normal file
104
usr.bin/shuffle/shuffle.1
Normal file
|
@ -0,0 +1,104 @@
|
|||
.\" $NetBSD: shuffle.1,v 1.8 2009/02/19 10:08:15 wiz Exp $
|
||||
.\"
|
||||
.\" Copyright (c) 1998
|
||||
.\" Perry E. Metzger. All rights reserved.
|
||||
.\"
|
||||
.\" Redistribution and use in source and binary forms, with or without
|
||||
.\" modification, are permitted provided that the following conditions
|
||||
.\" are met:
|
||||
.\" 1. Redistributions of source code must retain the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer.
|
||||
.\" 2. Redistributions in binary form must reproduce the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer in the
|
||||
.\" documentation and/or other materials provided with the distribution.
|
||||
.\" 3. All advertising materials mentioning features or use of this software
|
||||
.\" must display the following acknowledgment:
|
||||
.\" This product includes software developed for the NetBSD Project
|
||||
.\" by Perry E. Metzger.
|
||||
.\" 4. The name of the author may not be used to endorse or promote products
|
||||
.\" derived from this software without specific prior written permission.
|
||||
.\"
|
||||
.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
.\" IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
.\" NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
.\"
|
||||
.\"
|
||||
.Dd February 18, 2009
|
||||
.Dt SHUFFLE 1
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm shuffle
|
||||
.Nd print a random permutation of the command line arguments
|
||||
.Sh SYNOPSIS
|
||||
.Nm
|
||||
.Op Fl 0
|
||||
.Op Fl f Ar filename ...
|
||||
.Op Fl n Ar number
|
||||
.Op Fl p Ar number
|
||||
.Op Ar arg
|
||||
.Op Ar ...
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
.Nm
|
||||
program prints a random permutation (or
|
||||
.Dq shuffle )
|
||||
of its command line arguments.
|
||||
This can be useful in shell scripts for selecting a
|
||||
random order in which to do a set of tasks, view a set of files, etc.
|
||||
.Pp
|
||||
If the
|
||||
.Fl f
|
||||
option is given, the data is taken from that files' contents or if the
|
||||
filename is
|
||||
.Ar -
|
||||
.Dq stdin .
|
||||
.Pp
|
||||
If the
|
||||
.Fl n
|
||||
option is given, its argument is treated as a number, and the program
|
||||
prints a random permutation of the numbers greater than or equal to 0
|
||||
and less than the argument.
|
||||
.Pp
|
||||
If the
|
||||
.Fl p
|
||||
option is given, its argument is treated as a number, and the program
|
||||
prints that number of randomly selected lines or arguments in a random order.
|
||||
.Pp
|
||||
The
|
||||
.Fl 0
|
||||
option changes the field separator character from \en to \e0, so that
|
||||
the output is suitable to be sent to
|
||||
.Xr xargs 1
|
||||
(to handle filenames with whitespace in them).
|
||||
.Sh EXAMPLES
|
||||
.Bd -literal -offset indent
|
||||
$ shuffle a b c d
|
||||
c
|
||||
b
|
||||
d
|
||||
a
|
||||
$ shuffle -p 1 a b c d
|
||||
d
|
||||
$ shuffle -n 4 -p 2
|
||||
0
|
||||
3
|
||||
.Ed
|
||||
.Sh SEE ALSO
|
||||
.Xr jot 1 ,
|
||||
.Xr random 6
|
||||
.Sh HISTORY
|
||||
The
|
||||
.Nm
|
||||
program first appeared in
|
||||
.Nx 1.4 .
|
||||
.Sh AUTHORS
|
||||
Written by
|
||||
.An Perry E. Metzger
|
||||
.Aq perry@piermont.com .
|
220
usr.bin/shuffle/shuffle.c
Normal file
220
usr.bin/shuffle/shuffle.c
Normal file
|
@ -0,0 +1,220 @@
|
|||
/* $NetBSD: shuffle.c,v 1.21 2011/09/16 15:39:29 joerg Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1998
|
||||
* Perry E. Metzger. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgment:
|
||||
* This product includes software developed for the NetBSD Project
|
||||
* by Perry E. Metzger.
|
||||
* 4. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#ifndef lint
|
||||
__RCSID("$NetBSD: shuffle.c,v 1.21 2011/09/16 15:39:29 joerg Exp $");
|
||||
#endif /* not lint */
|
||||
|
||||
#include <sys/time.h>
|
||||
|
||||
#include <err.h>
|
||||
#include <errno.h>
|
||||
#include <limits.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <util.h>
|
||||
|
||||
static size_t *get_shuffle(size_t);
|
||||
__dead static void usage(void);
|
||||
static void get_lines(const char *, char ***, size_t *);
|
||||
static size_t get_number(const char *, int);
|
||||
|
||||
/*
|
||||
* get_shuffle --
|
||||
* Construct a random shuffle array of t elements
|
||||
*/
|
||||
static size_t *
|
||||
get_shuffle(size_t t)
|
||||
{
|
||||
size_t *shuffle;
|
||||
size_t i, j, k, temp;
|
||||
|
||||
shuffle = emalloc(t * sizeof(size_t));
|
||||
|
||||
for (i = 0; i < t; i++)
|
||||
shuffle[i] = i;
|
||||
|
||||
/*
|
||||
* This algorithm taken from Knuth, Seminumerical Algorithms,
|
||||
* 2nd Ed., page 139.
|
||||
*/
|
||||
|
||||
for (j = t - 1; j > 0; j--) {
|
||||
k = arc4random() % (j + 1);
|
||||
temp = shuffle[j];
|
||||
shuffle[j] = shuffle[k];
|
||||
shuffle[k] = temp;
|
||||
}
|
||||
|
||||
return shuffle;
|
||||
}
|
||||
|
||||
/*
|
||||
* usage --
|
||||
* Print a usage message and exit
|
||||
*/
|
||||
static void
|
||||
usage(void)
|
||||
{
|
||||
|
||||
(void) fprintf(stderr,
|
||||
"usage: %s [-0] [-f <filename>] [-n <number>] [-p <number>] [<arg> ...]\n",
|
||||
getprogname());
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* get_lines --
|
||||
* Return an array of lines read from input
|
||||
*/
|
||||
static void
|
||||
get_lines(const char *fname, char ***linesp, size_t *nlinesp)
|
||||
{
|
||||
FILE *fp;
|
||||
char *line;
|
||||
size_t size, nlines = 0, maxlines = 128;
|
||||
char **lines = emalloc(sizeof(char *) * maxlines);
|
||||
|
||||
if (strcmp(fname, "-") == 0)
|
||||
fp = stdin;
|
||||
else
|
||||
if ((fp = fopen(fname, "r")) == NULL)
|
||||
err(1, "Cannot open `%s'", fname);
|
||||
|
||||
while ((line = fgetln(fp, &size)) != NULL) {
|
||||
if (size > 0 && line[size - 1] == '\n')
|
||||
size--;
|
||||
lines[nlines] = emalloc(size + 1);
|
||||
(void)memcpy(lines[nlines], line, size);
|
||||
lines[nlines++][size] = '\0';
|
||||
if (nlines >= maxlines) {
|
||||
maxlines *= 2;
|
||||
lines = erealloc(lines, (sizeof(char *) * maxlines));
|
||||
}
|
||||
}
|
||||
lines[nlines] = NULL;
|
||||
|
||||
*linesp = lines;
|
||||
*nlinesp = nlines;
|
||||
if (strcmp(fname, "-") != 0)
|
||||
(void)fclose(fp);
|
||||
}
|
||||
|
||||
/*
|
||||
* get_number --
|
||||
* Return a number or exit on error
|
||||
*/
|
||||
static size_t
|
||||
get_number(const char *str, int ch)
|
||||
{
|
||||
char *estr;
|
||||
long number;
|
||||
|
||||
errno = 0;
|
||||
number = strtol(str, &estr, 0);
|
||||
if ((number == LONG_MIN || number == LONG_MAX) && errno == ERANGE)
|
||||
err(1, "bad -%c argument `%s'", ch, str);
|
||||
if (*estr)
|
||||
errx(1, "non numeric -%c argument `%s'", ch, str);
|
||||
if (number < 0)
|
||||
errx(1, "negative -%c argument `%s'", ch, str);
|
||||
return (size_t) number;
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
int nflag = 0, pflag = 0, ch;
|
||||
char *fname = NULL;
|
||||
size_t *shuffle = NULL;
|
||||
char **lines = NULL;
|
||||
size_t nlines = 0, pick = 0, i;
|
||||
char sep = '\n';
|
||||
|
||||
while ((ch = getopt(argc, argv, "0f:n:p:")) != -1) {
|
||||
switch(ch) {
|
||||
case '0':
|
||||
sep = '\0';
|
||||
break;
|
||||
case 'f':
|
||||
fname = optarg;
|
||||
break;
|
||||
case 'n':
|
||||
nlines = get_number(optarg, ch);
|
||||
nflag = 1;
|
||||
break;
|
||||
case 'p':
|
||||
pick = get_number(optarg, ch);
|
||||
pflag = 1;
|
||||
break;
|
||||
case '?':
|
||||
default:
|
||||
usage();
|
||||
}
|
||||
}
|
||||
argc -= optind;
|
||||
argv += optind;
|
||||
|
||||
if ((fname && nflag) || (nflag && (argc > 0)))
|
||||
usage();
|
||||
|
||||
if (fname != NULL)
|
||||
get_lines(fname, &lines, &nlines);
|
||||
else if (nflag == 0) {
|
||||
lines = argv;
|
||||
nlines = argc;
|
||||
}
|
||||
|
||||
if (nlines > 0)
|
||||
shuffle = get_shuffle(nlines);
|
||||
|
||||
if (pflag) {
|
||||
if (pick > nlines)
|
||||
errx(1, "-p specified more components than exist.");
|
||||
nlines = pick;
|
||||
}
|
||||
|
||||
for (i = 0; i < nlines; i++) {
|
||||
if (nflag)
|
||||
printf("%ld", (long)shuffle[i]);
|
||||
else
|
||||
printf("%s", lines[shuffle[i]]);
|
||||
putc(sep, stdout);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
Loading…
Reference in a new issue