0

I have a JSON file, which contains "threatLevel" : (an integer) multiple times. I grep the JSON to see if it contains a threatLevel which matches anything from my $THREAT_LEVEL variable, up to 10 (inclusive).

I have the following conditional flow of logic, which for the most part does the job.

#!/bin/bash

FILE="${CI_PROJECT_DIR}/iq.results.json"

if [ -z ${THREAT_LEVEL+x} ]; then # Checks if THREAT_LEVEL is unset. If unset, no checks will be made.
    echo "THREAT_LEVEL is unset. The job will ignore checking the results of $FILE.";
    exit 0
elif ! [[ $THREAT_LEVEL =~ ^[0-9]+$ ]]; then # Checks that the THREAT_LEVEL is only a positive integer.
    echo "Error - Invalid THREAT_LEVEL: THREAT_LEVEL must be a positive integer. It is currently set to $THREAT_LEVEL."
    exit 1
elif [ "$THREAT_LEVEL" -lt 1 ] || [ "$THREAT_LEVEL" -gt 10 ]; then # Checks that the THREAT_LEVEL is only between 1 and 10.
    echo "Error - Invalid THREAT_LEVEL: THREAT_LEVEL must be between 1 and 10. It is currently set to $THREAT_LEVEL."
    exit 1
else
    echo "THREAT_LEVEL is currently set to $THREAT_LEVEL"
    if [ "$THREAT_LEVEL" -lt 10 ]; then # If the THREAT_LEVEL is less than 10, grep for anything between THREAT_LEVEL and 10 inclusive.
        if grep -q -E '"threatLevel" : (['"$THREAT_LEVEL"'-9]|10)' "$FILE"; then
            echo "Detected dependencies with Threat Level of $THREAT_LEVEL or above in $FILE. Failing job.";
            exit 1
        else   
            echo "No dependencies with Threat Level of $THREAT_LEVEL or above detected in $FILE. Job allowed to pass";
            exit 0
        fi
    else
        if grep -q -E '"threatLevel" : 10' "$FILE"; then # Else THREAT_LEVEL must be 10. Grep for 10.
            echo "Detected dependencies with Threat Level of 10 in $FILE. Failing job.";
            exit 1
        else   
            echo "No dependencies with Threat Level of 10 or above detected in $FILE. Job allowed to pass.";
            exit 0
        fi
    fi
fi

I feel like both elif statements can be combined.

The first elif is only checking that the variable is a positive integer. It doesn't care if it's above 10, it could be 1000, it just can't be a string or a minus number or a decimal etc.

The second elif is the one which checks that it falls between 1-10 inclusively.

Is there a solution which meets both criteria?

jonrsharpe
  • 115,751
  • 26
  • 228
  • 437
cien
  • 43
  • 6
  • 2
    `^([1-9]|10)$`? – jonrsharpe Apr 20 '23 at 08:54
  • Or `(( 1 <= THREAT_LEVEL && THREAT_LEVEL <= 10 ))`. Note that it also fails if `THREAT_LEVEL` is unset or not an integer. – Renaud Pacalet Apr 20 '23 at 09:20
  • @jonrsharpe : This would reject a THREAD_LEVEL of 11. – user1934428 Apr 20 '23 at 09:23
  • 1
    @user1934428 ...yes? That's my understanding of what the OP's looking for: _"$THREAT_LEVEL variable, **up to 10 (inclusive)**"_. – jonrsharpe Apr 20 '23 at 09:31
  • @johnsharpe : You are right. I adapted my answer to this. – user1934428 Apr 20 '23 at 10:40
  • 2
    Given `I grep the JSON` and `grep -q -E '"threatLevel" : 10' "$FILE"`, etc. - is there some reason you can't use `jq` or similar JSON-aware tool? If you [edit] your question to include concise, testable sample input and expected output that covers all your use cases then we can best help you. – Ed Morton Apr 20 '23 at 12:24
  • The `bash` way to check if variable is unset is `[[ ! -v THREAT_LEVEL ]]`; no parameter expansions needed. – chepner Apr 20 '23 at 12:49

1 Answers1

-1

To test that THREAD_LEVEL is an integer, I would do it as

if [[ $THREAD_LEVEL == *[^0-9]* ]]
then
  echo Not an integer: "'$THREAD_LEVEL'"
else
  ...

This simply checks whether there is a non-digit in the variable.

To test for valid ranges, I would do something like

if (( THREAD_LEVEL > 9 && THREAD_LEVEL != 0 ))
then
  echo Thread level must be an integer from 1 to 10
else 
  ...

However this could fail if THREAD_LEVEL is supplied with a leading zero. For instance setting THREAD_LEVEL to 09 would produce the error message value too great for base, since the leading zero would indicate an octal number. I therefore suggest to first sanitize the THREAD_LEVEL by removing leading zeroes. Putting everything together, we have:

shopt -s extglob
THREAD_LEVEL=${THREAD_LEVEL##+(0)} # Remove leading zeroes
if [[ $THREAD_LEVEL == *[^0-9]* ]]
then
  ;# We know here that THREAD_LEVEL is not a natural number
elif [[ -z $THREAD_LEVEL ]]
then
  ;# THREAD_LEVEL originally consisted only of zeroes
elif ((THREAD_LEVEL > 10 ))
  ;# THREAD_LEVEL is too large
else
  ;# THREAD LEVEL is OK
  ...
fi

Note that extglob is needed here to enable the pattern +(0) to mean _one or more occurances of 0.

user1934428
  • 19,864
  • 7
  • 42
  • 87