'Print the missing number in a unique sequential list with an arbitrary starting range or starting from 1

This question is similar to How can I find the missing integers in a unique and sequential list (one per line) in a unix terminal?.

The difference being is that I want to know if it is possible to specify a starting range to the list

I have noted the following provided solutions:

awk '{for(i=p+1; i<$1; i++) print i} {p=$1}' file1

and

perl -nE 'say for $a+1 .. $_-1; $a=$_'

file1 is as below:

5
6
7
8
15
16
17
20

Running both solutions, it gives the following output:

1
2
3
4
9
10
11
12
13
14
18
19

Note that the output start printing from 1.

Question is how to pass an arbitrary starting/minimum to start with and if nothing is provided, assume the number 1 as the starting/minimum number?

9
10
11
12
13
14
18
19

Yes, sometimes you will want the starting number to be 1 but sometimes you will want the starting number as the least number from the list.



Solution 1:[1]

Slight variations of those one-liners to include a start point:

awk

# Optionally include start=NN before the first filename
$ awk 'BEGIN { start= 1 }
       $1 < start { next }
       $1 == start { p = start }
       { for (i = p + 1; i < $1; i++) print i; p = $1}' start=5 file1
9
10
11
12
13
14
18
19
$ awk 'BEGIN { start= 1 }
       $1 < start { next }
       $1 == start { p = start }
       { for (i = p + 1; i < $1; i++) print i; p = $1}' file1
1
2
3
4
9
10
11
12
13
14
18
19

perl

# Optionally include -start=NN before the first file and after the --
$ perl -snE 'BEGIN { $start //= 1 }
             if ($_ < $start) { next }
             if ($_ == $start) { $a = $start }
             say for $a+1 .. $_-1; $a=$_' -- -start=5 file1
9
10
11
12
13
14
18
19
$ perl -snE 'BEGIN { $start //= 1 }
             if ($_ < $start) { next }
             if ($_ == $start) { $a = $start }
             say for $a+1 .. $_-1; $a=$_' -- file1
1
2
3
4
9
10
11
12
13
14
18
19

Solution 2:[2]

You can use your awk script, slightly modified, and pass it an initial p value with the -v option:

$ awk 'BEGIN{p=p<1?1:p} {for(i=p; i<$1; i++) print i} {p=p<=$1?$1+1:p}' file1
1
2
3
4
9
10
11
12
13
14
18
19
$ awk -v p=10 'BEGIN{p=p<1?1:p} {for(i=p; i<$1; i++) print i} {p=p<=$1?$1+1:p}' file1
10
11
12
13
14
18
19

The BEGIN block initializes p to 1 if it is not specified or set to 0 or a negative value. The loop starts at p instead of p+1, and the last block assigns $1+1 to p (instead of $1), if and only if p is less or equal $1.

This assumes that the default (1) is the minimum starting number you would want. If you would like to start from 0 or even from a negative number just replace BEGIN{p=p<1?1:p} by BEGIN{p=(p==""?1:p)}:

$ awk -v p=-2 'BEGIN{p=(p==""?1:p)} {for(i=p; i<$1; i++) print i} {p=p<=$1?$1+1:p}' file1
-2
-1
0
1
...

Solution 3:[3]

Using Raku (formerly known as Perl_6)

raku -e 'my @a=lines.map: *.Int; .put for (@a.Set (^) @a.minmax.Set).sort.map: *.key;'

Sample Input:

5
6
7
8
15
16
17
20

Sample Output:

9
10
11
12
13
14
18
19

Here's an answer coded in Raku, a member of the Perl-family of programming languages. No, it doesn't address the OP's request for a user-definable starting point. Instead the code above is a general solution that computes the input's minimum Int and counts up from there, returning any missing Ints found up--to the input's maximum Int.

Really need a user-defined lower limit? Try the following code, which allows you to set a $init variable:

~$ raku -e 'my @a=lines.map: *.Int; my $init = 1; .put for (@a.Set (^) ([email protected]).Set).sort.map: *.key;' 
1
2
3
4
9
10
11
12
13
14
18
19

For explanation and shorter code (including single-line return and/or return without sort), see the link below.

https://stackoverflow.com/a/72221301/7270649
https://raku.org

Solution 4:[4]

not as elegant as i hoped :

< file | mawk '
         BEGIN {    _= int(_)^(\
               ( ORS = "")<_) 
         }  { ___[ __= $0 ] }
         END { 
            do { 
                print _ in ___ \
                      ? "" : _ "\n" 
            } while(++_ < __) }' \_=10          
10
11
12
13
14
18
19

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Shawn
Solution 2
Solution 3
Solution 4