Create Dynamic if condition

Create Dynamic If condition

Hi,
I have a file color.txt which has data as shown below

Red
Blue
Green
Yellow
White
Pink
Black

Based on a variable I execute a tail command as shown below

tail -${LEFT_OVR} color.txt

LEFT_OVR can be any number less than count of number of lines in a file

so if LEFT_OVR=2, then output would be

Pink
Black

Based on output of tail command I need to build a dynamic If condition, which will look something like this

if [ "$color" = "Pink" ] || [ "$color" = "Black" ]

I'm planning to do something like this

tail -${LEFT_OVR} color.txt > tail_out
one_line=`awk 'BEGIN { ORS = " " } { print }' tail_out`

COND=""
for c in $one_line
do
COND="[ color = $c ] $COND"
done

Next I would check for occurrence of ] [ and replace with ] || [

Any ideas if there is something easier to achieve similar result?

With LEFT_OVR=4 , try

tail -${LEFT_OVR} color.txt | { while read CND; do CMD+="[ color = $CND ] || "; done; echo ${CMD% || }; }
[ color = Yellow ] || [ color = White ] || [ color = Pink ] || [ color = Black ]

Unfortunately, you'll need to use the unloved eval to take advantage of above, or output it into a temp file that you source, then.

Would something like this, base on a case statement work?

$ cat case_test
t1=Red
t2=Yellow
t3=Green
t4=Brown
t5=Blue
t6=Pink
t7=Black

case $1 in
 $t1) echo "The red ball is worth 1 point."         ;;
 $t2) echo "The yellow ball is worth 2 points."     ;;
 $t3) echo "The green ball is worth 3 points."      ;;
 $t4) echo "The brown ball is worth 4 points."      ;;
 $t5) echo "The blue ball is worth 5 points."       ;;
 $t6) echo "The pink ball is worth 6 points."       ;;
 $t7) echo "The black ball is worth 7 points."      ;;
 *)   echo "Any other option is a foul."            ;;
esac

I get the following simple sample output:-

$ ./case_test Yellow
The yellow ball is worth 2 points.
$ ./case_test White 
Any other option is a foul.
$

You could easily set the variables t1, t2, t3 etc. based on your tail output and set all the others to be dummy or the like to effectively switch off those tests.

Does that give you an angle?

Robin

Another way might be to build up an array from the tail output and then have a loop around the if statement to check each one set in turn. It depends quite what you need to achieve I suppose.

Can you elaborate on the overall desired need?

Robin

With a recent bash , try

[[ "$(tail -${LEFT_OVR} color.txt | tr '\n' ' ' )" =~ "$color" ]] && echo good || echo bad
2 Likes

Hi,
Can you explain, how above command works, in building the if condition?

I love arrays:

#!/bin/bash
C=1
declare -A  BALL

while read color;do
	BALL[${color,,}]=$C
	C=$(( $C + 1 ))
done<"${0/sh/txt}"

echo "Ball $1 is worth ${BALL[${1,,}]}"

Have a good week :slight_smile:

EDIT-Note:
My files were named identical but with another file extension (sh/txt).
Though, to be accurate for snooker values, the colors would need to be in order.

EDIT2:
Outputs like:

+ bin $ sh ~/tmp/sample.sh pink
Ball pink is worth 6
:) bin $ sh ~/tmp/sample.sh red 
Ball red is worth 1

EDIT3 - Explanation:

C=1
declare -A  BALL

Sets variable C to 1, and declares varable BALL as ALPHA indexed Array. (not quiet sure on the ALPHA label, ity my 'donkey-bridge')

while read color;do
....
done<"${0/sh/txt}"

Read from file $0 (the execute[d|r] script), but remove first occourence of sh with txt within its filename,
expand each line to the only passed variable color .
Since the (in this example) used scriptname and content-file-name are identical but their file extension not, this works quite fine.

	BALL[${color,,}]=$C
	C=$(( $C + 1 ))

${color,,} makes the content of variable color to small letters, since usualy people forget to press shift when passing options or arguments to commands.
So it set the array index $color to value $C, then increment that value. (could be shortened to ((C++)) in this case, or ((counter++)) whatsoever you use for an index/counter)

echo "Ball $1 is worth ${BALL[${1,,}]}"

Finaly we print out the the desired information. 'downcode' the passed argument to small letters, just to be sure, so it matches the array index, which is now set to letters (the color names).

hth

2 Likes

That is an "abbreviated if construct" in recent bash (and other recent shells). If the result of the [[ ... ]] compound command is true, the && command is executed, if false, the || command.
cf. man bash :

So above looks for the $color in the string built from the LEFT_OVR lines tail ed from the file.