——#!/usr/bin/perl
=encoding utf8
=begin metadata
Name: seq
Description: print a numeric sequence
Author: Michael Mikonos
License: artistic2
=end metadata
=cut
use
strict;
my
$Program
= basename($0);
my
$begin
= 1;
my
$step
= 1;
my
$ender
;
my
$format
=
"%g"
;
my
$term
=
"\n"
;
sub
usage {
warn
"usage: $Program [-f format] [-s string] [begin [step]] end\n"
;
exit
EX_FAILURE;
}
while
(
@ARGV
&&
$ARGV
[0] =~ /^-/) {
my
$opt
=
shift
;
if
(
$opt
eq
'--'
) {
last
;
}
elsif
(
$opt
eq
'-s'
) {
$term
=
shift
;
}
elsif
(
$opt
eq
'-f'
) {
$format
=
shift
;
}
elsif
(
$opt
=~ m/\A\-?[0-9]/) {
unshift
@ARGV
,
$opt
;
last
;
}
else
{
warn
"$Program: unexpected option: '$opt'\n"
;
usage();
}
}
if
(
@ARGV
== 0) {
usage();
}
elsif
(
@ARGV
== 1) {
$ender
= getnum(
$ARGV
[0]);
}
elsif
(
@ARGV
== 2) {
$begin
= getnum(
$ARGV
[0]);
$ender
= getnum(
$ARGV
[1]);
}
elsif
(
@ARGV
== 3) {
$begin
= getnum(
$ARGV
[0]);
$step
= getnum(
$ARGV
[1]);
$ender
= getnum(
$ARGV
[2]);
}
else
{
warn
"$Program: extra argument '$ARGV[3]'\n"
;
usage();
}
if
(
$step
== 0) {
warn
"$Program: illegal step value of zero\n"
;
exit
EX_FAILURE;
}
if
(
$ender
<
$begin
) {
if
(
@ARGV
!= 3) {
$step
= -
$step
;
}
elsif
(
$step
> 0) {
warn
"$Program: needs negative decrement\n"
;
exit
EX_FAILURE;
}
}
else
{
if
(
$step
< 0) {
warn
"$Program: needs positive increment\n"
;
exit
EX_FAILURE;
}
}
my
$head
= 1;
my
$count
= floor((
$ender
-
$begin
) /
$step
);
for
(0 ..
$count
) {
if
(
$head
) {
$head
= 0;
}
else
{
$term
;
}
printf
$format
,
$begin
+
$_
*
$step
;
}
"\n"
;
exit
EX_SUCCESS;
sub
getnum {
my
$n
=
shift
;
if
(
$n
!~ m/\A[\+\-]?[0-9]+(\.[0-9]+)?\Z/) {
warn
"$Program: invalid number '$n'\n"
;
exit
EX_FAILURE;
}
return
$n
;
}
__END__
=head1 NAME
seq - print a numeric sequence
=head1 SYNOPSIS
seq [OPTIONS] LAST
seq [OPTIONS] FIRST LAST
seq [OPTIONS] FIRST INCR LAST
=head1 DESCRIPTION
seq writes a list of numbers to standard output separated by a newline character.
If only LAST is provided the sequence starts from 1 and the increment is 1.
LAST may be negative, in which case the sequence starts from 1 with the increment of -1.
When only FIRST and LAST are specified the increment will be either 1 or -1 based on whether FIRST is greater.
Sequences are inclusive of FIRST and LAST, so "seq 3 3" results in the sequence "3".
When an increment is needed other than 1 or -1, the INCR argument should be used.
Zero is not a valid increment.
Positive numbers may optionally include a '+' prefix.
Floating point numbers may be entered in decimal notation (e.g. 0.2223).
=head2 OPTIONS
The following options are available:
=over 4
=item -f FORMAT
Set a printf format specifier instead of the default '%g'
=item -s STRING
Separate each number with STRING instead of the newline character
=back
=head1 BUGS
Corrupt printf format specifiers may be entered.
=head1 AUTHOR
Written by Michael Mikonos.
=head1 COPYRIGHT
Copyright (c) 2023 Michael Mikonos.
This code is licensed under the Artistic License 2.
=cut