#!/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; our $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: Integer 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; }