1

I would like to test if a list of integer values (e.g stored in a file, one per line) is strictly increasing, using a bash script.

Is there any simple/concise way to achieve that?

6

Check if the file's contents remain the same after sorting numerically and filtering duplicated lines:

cmp file <(sort -n file | uniq)

At least GNU sort can do this check directly:

sort -c -u -n file

(The POSIX sort documentation mentions this too so it should be supported everywhere.)

  • But that won't work for strict increasing, will it? – sdabet Jun 25 '15 at 9:41
  • @fiddler if you omit the "filtering duplicated lines" part you'll get your solution for a strictly increasing sequence – roaima Jun 25 '15 at 9:48
  • The sort solution seems perfect. – sdabet Jun 25 '15 at 9:49
  • Note that GNU sort (as opposed to Solaris sort for instance) seems to read the input fully before reporting the disorder even if the disorder is on the second line. – Stéphane Chazelas Jun 25 '15 at 10:01
  • 1
    Yes, even when checking, it starts by filling a buffer. – Stephen Kitt Jun 25 '15 at 10:14
2

If you mean, check that each line is a decimal integer that is one plus the decimal integer in the previous line, then:

awk 'NR == 1 {n = $0; next}
     $0 != n+1 {status = 1; exit}
     {n = $0}
     END {exit status}'

Replace the $0 != n+1 with $0 <= n to check for strict increasing by any value, not only one. In that case though, you'll probably prefer the sort -c approach unless you want it to stop reading at the first disorder, or you want to support number formats (hexadecimal, floating point notation...) not supported by sort (like when your sort doesn't support -g)

  • strictly increasing simply means that for an integer sequence, the current value is greater than the previous. It makes no assumption that it's increasing by one, or even by any regular amount. Just that each number is the sequence is bigger than the previous. – roaima Jun 25 '15 at 9:50
1

With awk:

awk 'length(p)&&++p!=$0{print "Not OK";exit};{p=$0}' file

for increasing one per line. To check current is bigger than previous:

awk 'length(p)&&++p<=$0{print "Not OK";exit};{p=$0}' file
0

The extremely concise version would be something like this

#!/bin/bash
awk 'NR > 1 && $1 < prev { printf( "error at line %d\n", NR); exit; } { prev = $1 } '  $1

This non concise code would be

#!/bin/bash
l=1     #line number count
p=0     #previous line value
for f in `cat $1`
do
    if [ \( "$f" -lt "$p" \) -a \( "$l" -ne "1" \) ]   #chk for all lines, except first
        then    echo "$f is less than $p on Line $l"
        break
    else
        p=$f  #set previous
    fi
    l=$(expr $l + 1)   #increment line number
done

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.