program rand
use M_io, only : fileread
use M_strings, only : notabs
use M_random, only : scramble, init_random_seed_by_system_clock
use M_framework, only : stderr
use M_kracken, only : kracken, lget, sgets, iget, igets ! add command-line parser module
implicit none
character(len=4096),allocatable :: FILENAMES(:)
character(len=:),allocatable :: pageout(:) ! array to hold file in memory
integer,allocatable :: indx(:)
integer :: i,j,k,n
integer,allocatable :: vals(:)
integer :: icount
!-----------------------------------------------------------------------------------------------------------------------------------
call kracken('rand','-help .F. -version .f. -e .F. -n -1 -i') ! define command arguments,default values and crack command line
call help_usage(lget('rand_help')) ! if -help option is present, display help text and exit
call help_version(lget('rand_version')) ! if -version option is present, display version text and exit
FILENAMES=sgets('rand_oo')
k=iget('rand_n')
vals=igets('rand_i')
call init_random_seed_by_system_clock()
!-----------------------------------------------------------------------------------------------------------------------------------
DONE : block
!-----------------------------------------------------------------------------------------------------------------------------------
if(lget('rand_e'))then
n=size(FILENAMES)
indx=scramble(n)
n=merge(min(k,n),n,k.ge.0)
write(*,'(a)')(trim(FILENAMES(indx(i))),i=1,n)
exit DONE
endif
!-----------------------------------------------------------------------------------------------------------------------------------
if(size(vals).eq.2)then
indx=scramble(abs(vals(2)-vals(1))+1)+min(vals(1),vals(2))-1
n=merge(min(k,size(indx)),size(indx),k.ge.0)
write(*,'(i0)')(indx(i),i=1,n)
exit DONE
endif
!-----------------------------------------------------------------------------------------------------------------------------------
icount=size(FILENAMES)
if(icount==0)FILENAMES=['-']
do j=1,max(icount,1)
! allocate character array and copy file into it
if(FILENAMES(j).eq.'-')then
call fileread(5,pageout)
else
call fileread(FILENAMES(j),pageout)
endif
if(.not.allocated(pageout))then
call stderr('*rand* failed to load file ',FILENAMES(j))
else
n=size(pageout)
indx=scramble(n)
n=merge(min(k,n),n,k.ge.0)
write(*,'(a)')(trim(pageout(indx(i))),i=1,n)
deallocate(pageout) ! release memory
endif
enddo
endblock DONE
contains
subroutine help_usage(l_help)
implicit none
character(len=*),parameter :: ident="@(#)help_usage(3f): prints help information"
logical,intent(in) :: l_help
character(len=:),allocatable :: help_text(:)
integer :: i
logical :: stopit=.false.
stopit=.false.
if(l_help)then
help_text=[ CHARACTER(LEN=128) :: &
'NAME ',&
' rand - [M_random] generate pseudo-random permutations of file lines, whole ',&
' numbers, or strings ',&
' (LICENSE:PD) ',&
' ',&
'SYNOPSIS ',&
' syntax: ',&
' ',&
' rand FILES(s) [ -n] ',&
' rand STRINGS -e [ -n] ',&
' rand -i LO-HI [ -n] ',&
' ',&
'DESCRIPTION ',&
' Generates pseudorandom permutations, similar to the shuf(1) command. ',&
' Writes pseudo-random permutations of: ',&
' ',&
' o the lines in a file ',&
' o a range of whole numbers ',&
' o a list of strings ',&
' ',&
'OPTIONS ',&
' FILES(s) files to use as input ',&
' -e treat each ARG as an input line ',&
' -i LO HI treat each number LO through HI as an input line ',&
' -n output at most COUNT lines (per file) ',&
' --help display this help and exit ',&
' --version output version information and exit ',&
' ',&
'EXAMPLES ',&
' Sample usage: ',&
' ',&
' # generate a random number from 0 to 100 ',&
' rand -i 0 100 -n 1 ',&
' ',&
' # randomly pick a line from a file ',&
' rand -n 1 MYFILE.TXT ',&
' ',&
' # randomly select xterm(1) color ',&
' xterm -bg `rand green black gray blue -e -n 1` ',&
' ',&
' # randomly sleep 10 to 30 seconds ',&
' sleep `rand 10 30 -n 1` ',&
' ',&
'AUTHOR ',&
' John S. Urban ',&
' ',&
'LICENSE ',&
' Public Domain ',&
' ',&
'']
WRITE(*,'(a)')(trim(help_text(i)),i=1,size(help_text))
stop ! if --help was specified, stop
endif
end subroutine help_usage
!>
!!##NAME
!! rand - [M_random] generate pseudo-random permutations of file lines, whole
!! numbers, or strings
!! (LICENSE:PD)
!!
!!##SYNOPSIS
!!
!! syntax:
!!
!! rand FILES(s) [ -n]
!! rand STRINGS -e [ -n]
!! rand -i LO-HI [ -n]
!!
!!##DESCRIPTION
!! Generates pseudorandom permutations, similar to the shuf(1) command.
!! Writes pseudo-random permutations of:
!!
!! o the lines in a file
!! o a range of whole numbers
!! o a list of strings
!!
!!##OPTIONS
!! FILES(s) files to use as input
!! -e treat each ARG as an input line
!! -i LO HI treat each number LO through HI as an input line
!! -n output at most COUNT lines (per file)
!! --help display this help and exit
!! --version output version information and exit
!!
!!##EXAMPLES
!!
!! Sample usage:
!!
!! # generate a random number from 0 to 100
!! rand -i 0 100 -n 1
!!
!! # randomly pick a line from a file
!! rand -n 1 MYFILE.TXT
!!
!! # randomly select xterm(1) color
!! xterm -bg `rand green black gray blue -e -n 1`
!!
!! # randomly sleep 10 to 30 seconds
!! sleep `rand 10 30 -n 1`
!!
!!##AUTHOR
!! John S. Urban
!!
!!##LICENSE
!! Public Domain
subroutine help_version(l_version)
implicit none
character(len=*),parameter :: ident="@(#)help_version(3f): prints version information"
logical,intent(in) :: l_version
character(len=:),allocatable :: help_text(:)
integer :: i
logical :: stopit=.false.
stopit=.false.
if(l_version)then
help_text=[ CHARACTER(LEN=128) :: &
'@(#)PRODUCT: GPF (General Purpose Fortran) utilities and examples>',&
'@(#)PROGRAM: rand(1)>',&
'@(#)DESCRIPTION: random shuffle of lines in a file or strings or a range of whole numbers>',&
'@(#)VERSION: 2.0, 2022-01-08>',&
'@(#)AUTHOR: John S. Urban>',&
'@(#)LICENSE: Public Domain. This is free software: you are free to change and redistribute it.>',&
'@(#) There is NO WARRANTY, to the extent permitted by law.>',&
'@(#)COMPILED: 2023-04-12 02:29:17 UTC-240>',&
'']
WRITE(*,'(a)')(trim(help_text(i)(5:len_trim(help_text(i))-1)),i=1,size(help_text))
stop ! if --version was specified, stop
endif
end subroutine help_version
end program rand