Musaveer STARk
Musaveer STARk

Reputation: 17

Shell script to find the missing numbers in a file

Below is the example file I have with name Weeks:

2002
2004
2005
2006
2010

And I wanted a simple script to display the missing number from the files. I tried the below script but didn't get expected results.

#!/bin/bash
filename='Weeks'
Sw=2001
while read line; do
  #Reading each line.
  if [ $line != $Sw ]
  then
    Sw=$(($Sw+1))
    echo "$line"
  else
    Sw=$(($Sw+1))
  fi
done < $filename

Expected output is:

2001
2003
2007
2008
2009

Please help me I don't why the above script is not giving me correct output.

Upvotes: 0

Views: 964

Answers (1)

Boldewyn
Boldewyn

Reputation: 82754

comm -13 Weeks <(seq 2001 2010)

That should do the trick.

seq:

NAME
       seq - print a sequence of numbers

SYNOPSIS
       seq [OPTION]... LAST
       seq [OPTION]... FIRST LAST
       seq [OPTION]... FIRST INCREMENT LAST

DESCRIPTION
       Print numbers from FIRST to LAST, in steps of INCREMENT.
       [...]

comm:

NAME
       comm - compare two sorted files line by line

SYNOPSIS
       comm [OPTION]... FILE1 FILE2

DESCRIPTION
       Compare sorted files FILE1 and FILE2 line by line.

       When FILE1 or FILE2 (not both) is -, read standard input.

       With no options, produce three-column output.  Column one contains lines unique to FILE1, column two contains lines unique to FILE2, and column three contains lines common to both files.

       -1     suppress column 1 (lines unique to FILE1)

       -2     suppress column 2 (lines unique to FILE2)

       -3     suppress column 3 (lines that appear in both files)
       [...]

The <(...) syntax tricks comm into believing, that the output of seq is actually a file.

In your original script there is an initial logic error, that follows execution until the end. Ask yourself, what happens in the very first iteration of the while loop: $Sw is 2001, $line is 2002. $Sw will be incremented to 2002, but in the next iteration compared to 2004 and so on.

Additionally you print $line, which is the wrong variable.

A possible (albeit a bit inefficient) solution for the logic would be to nest another for loop in the while loop to look for and print items missing between the last $line value (that you need to store at the end of each loop in another variable) and the current $line value.

Upvotes: 3

Related Questions