I decided to try to duplicate the functionality of the GNU utility seq, and add a few features, such as hexadecimal input and/or output, and descending ranges. Negative numbers are somewhat supported. I really wanted completely dynamic decimal support, but failed to implement it easily, so I gave it up for the time being.
Someone pointed out that this example with GNU seq's --format parameter and a custom, negative, decimal increment (decrement) value demonstrates a lot of what my seq version features:
$ seq --format '%05.2f' 2 -.5 -1 02.00 01.50 01.00 00.50 00.00 -0.50 -1.00
$ ./st-seq.pl 8 13 8 9 10 11 12 13
$ ./st-seq.pl 8 13 --pad 3 008 009 010 011 012 013
$ ./st-seq.pl 8 13 --hexout 8 9 a b c d
$ ./st-seq.pl aa bb --hexin --hexout --sep ' ' aa ab ac ad ae af b0 b1 b2 b3 b4 b5 b6 b7 b8 b9 ba bb
$ ./st-seq.pl 13 8 --equalwidth 13 12 11 10 09 08
$ ./st-seq.pl 100 500 --increment 100 100 200 300 400 500
$ ./st-seq.pl 1017 1013 --pad 5 --separator ', ' 01017, 01016, 01015, 01014, 01013
$ ./st-seq.pl 1017 1004 --increment 2 1017 1015 1013 1011 1009 1007 1005
You might need to use "--" after possibly passing other options so the negative numbers won't be interpreted as arguments. This is shell behavior.
$ ./st-seq.pl -- -5 -1 -5 -4 -3 -2 -1
Negative range and negative numbers:
$ ./st-seq.pl -- -1 -5 -1 -2 -3 -4 -5
$ ./st-seq.pl --format '%.2f' -- -1 -5 -1.00 -2.00 -3.00 -4.00 -5.00
$ ./st-seq.pl --increment 0.5 -- -2.5 1 -2.5 -2 -1.5 -1 -0.5 0 0.5 1 $ ./st-seq.pl --increment 0.4 -- -2.5 1 -2.5 -2.1 -1.7 -1.3 -0.9 -0.5 -0.1 0.3 0.7
#!/usr/bin/perl # Copyright (c) 2012, Svendsen Tech # All rights reserved. # # Author: Joakim Svendsen # st-seq - seq on steroids use warnings; use strict; use File::Basename; use Getopt::Long;Linux Perl All Categoriesour $VERSION = '1.02';
main(); sub main { my %opt; GetOptions( 'hexin' => \$opt{hexin}, 'hexout' => \$opt{hexout}, 'help' => \$opt{help}, 'equalwidth' => \$opt{equalwidth}, 'format=s' => \$opt{format}, 'pad=i' => \$opt{pad}, 'separator=s' => \$opt{separator}, 'increment=s' => \$opt{increment}, ) or die "Unable to process arguments!\nError: $!"; print_help() if $opt{help}; die "Missing start and end decimal/hex values\nUse --help for help.\n" if @ARGV == 0; die "Missing end decimal/hex value\nUse --help for help.\n" if @ARGV == 1; my ($first_num, $second_num) = @ARGV; my $regex = $opt{hexin} ? qr'[^a-f0-9]' : qr'[^\d\-.]'; die "Illegal characters or pattern found in first decimal/hex value\n" if $first_num =~ m/$regex/i; die "Illegal characters or pattern found in second decimal/hex value\n" if $second_num =~ m/$regex/i; my $format = $opt{format} ? $opt{format} : '%s'; my $increment = $opt{increment} ? $opt{increment} : 1; # Get a "boolean" for whether the first number is the lowest. my $first_is_lower = get_lower($first_num, $second_num, $opt{hexin}); # Set padding if --equalwidth or --pad are specified. Otherwise set to 0 (false). # --equalwidth overrides --pad. my $pad = 0; if ($opt{equalwidth}) { # If the first number is the lowest, the number containing the max # amount of digits must be the other one, and vice versa. $pad = $first_is_lower ? length $second_num : length $first_num; } elsif ($opt{pad}) { $pad = $opt{pad}; } my @output_list = enumerate_range( $first_num, $second_num, $format, $increment, $pad, $opt{hexin}, $opt{hexout}, $first_is_lower ); print join $opt{separator} ? $opt{separator} : "\n", @output_list; print "\n"; } sub print_help { my $prog_name = basename $0; print <] [--equalwidth] [--increment ] [--separator ] [--help] FIRST LAST --pad: Pad with leading zeroes to make the number contain at least the specified number of digits. --hexin: Interpret specified FIRST and LAST numbers as hexadecimal. --hexout: Display output as hexadecimal values. The default is decimal, even when --hexin is specified. --format: A sprintf-type format to display numbers in. Overrides --pad and --equalwidth. --equalwidth: Pads with leading zeroes to make all numbers the same width, if necessary. Not in effect if using --hexout. Overrides --pad. --increment: Decimal that determines the steps between numbers. --separator: Separator between elements. Default "\\n". FIRST: The first number in the range to start counting up or down from. It can be higher than the LAST number to count down. LAST: The last number in the range to count up to or down towards, from FIRST. Examples: $prog_name --sep ', ' 5 1 $prog_name --pad 3 99 102 $prog_name --hexin --hexout 10 20 $prog_name --equalwidth 42 1004 --separator ' ' EOF exit; } sub get_lower { my ($first_number, $second_number, $hexin) = @_; if ($hexin) { return (hex $first_number < hex $second_number) ? 1 : 0; } return ($first_number < $second_number) ? 1 : 0; } sub enumerate_range { my ($start_num, $end_num, $format, $increment, $pad, $hex_in, $hex_out, $first_is_lower) = @_; my ($start_dec, $end_dec); if ($hex_in) { $start_dec = hex $start_num; $end_dec = hex $end_num; } else { $start_dec = $start_num; $end_dec = $end_num; } my @num_list; # Code duplication. Meh. if ($first_is_lower) { # Increment for each iteration when first is lower. for (my $decimal = $start_dec; $decimal <= $end_dec; $decimal += $increment) { if ($hex_out) { push @num_list, sprintf '%x', $decimal; } else { if ($format ne '%s') { push @num_list, sprintf $format, $decimal; } elsif ($pad) { push @num_list, sprintf "%0${pad}d", $decimal; } else { push @num_list, $decimal; } } } # end of for loop } # This is when the first number is higher than the last. else { # Decrement for each iteration when first is higher. for (my $decimal = $start_dec; $decimal >= $end_dec; $decimal -= $increment) { if ($hex_out) { push @num_list, sprintf '%x', $decimal; } else { if ($format ne '%s') { push @num_list, sprintf $format, $decimal; } elsif ($pad) { push @num_list, sprintf "%0${pad}d", $decimal; } else { push @num_list, $decimal; } } } # end of for loop } return @num_list; }
Minimum cookies is the standard setting. This website uses Google Analytics and Google Ads, and these products may set cookies. By continuing to use this website, you accept this.