Better solution for this "if" spaghetti


 
Thread Tools Search this Thread
Top Forums Shell Programming and Scripting Better solution for this "if" spaghetti
# 1  
Old 09-19-2018
Better solution for this "if" spaghetti

Hello everyone,

I'm stuck and I need some help with rewriting the following code. It's ugly af and I'm not sure which direction to go.

Code:
err=0
trap 'err=1' ERR


# these 2x env. vars will be set by another script to either
# a value or to 'null' (4 chars)
TAG="${TAG}"
VALUE="${VALUE}"

# form the cmd to be executed
BASE_CMD="base_cmd arg1"
# if err=0, append "arg2"
SUCC_CMD="$BASE_CMD arg2"
# if err=1, change arg2 to arg3
FAIL_CMD="${SUCC_CMD//arg2/arg3}"
# if $TAG and $VALUE are set and err=0, do this:
SUCC_CMD2="$SUCC_CMD $TAG $VALUE arg4"
# same as above but if err=1
FAIL_CMD2="${SUCC_CMD2//arg4/arg5}"

# clear the 'null'
if [ "${AMI_TAG_KEY}" == 'null' ];then
        AMI_TAG_KEY=''
        AMI_TAG_VALUE=''
fi

# according to err, launch the cmds we created above
# assume $VALUE is null when $TAG is null
if [ "${err}" == "0" ] && [ ! -z "${TAG}" ];then
  $SUCC_CMD2
elif [ "${err}" == "0" ] && [ -z "${TAG}" ];then
  $SUCC_CMD
elif [ "${err}" != "0" ] && [ ! -z "${TAG}" ];then
  $FAIL_CMD2
  exit 1
elif [ "${err}" != "0" ] && [ -z "${TAG}" ];then
  $FAIL_CMD
  exit 1
fi

The idea is that I would like to avoid code duplicate (first segment) and then launch a specific command according to some logic (2nd and 3rd section). The only issue is that it looks ugly af to me and I'm sure there's a better way to rewrite it.


Any help or direction would be appreciated.


Thx in advance.
# 2  
Old 09-19-2018
You might be better with a case statement. The structure is like this.

Code:
case "${err}" in
        0) echo "I saw value ${err}" ;;
        1) echo "I saw value ${err}"
            echo "This means something. ;;
        2) echo "I saw value ${err}"
            err=5        ;;
        *) echo "I saw something else - ${err} so....."
            echo "Panic" ;;
esac



I hope that this helps,
Robin
This User Gave Thanks to rbatte1 For This Post:
# 3  
Old 09-19-2018
I was thinking about a case statement but I have to evaluate $err and the value of $TAG together and I'm not sure how that would look and work. I guess something like this:

Code:
case "${err}" in
        "0")
        [ "${err}" == "0" ] && [ ! -z "${TAG}" ]
        $SUCC_CMD2
        ;;
        "1")
        [ "${err}" == "0" ] && [ ! -z "${TAG}" ]
        $FAIL_CMD2
        ;;
        *) printf "Something went wrong"
           exit 1
         ;;
esac

# 4  
Old 09-19-2018
No case, no if, just shell "parameter expansion". May be not that easy to maintain in the long term (and uses the deprecated eval, but safely as the conditions are clearly defined):
Code:
eval "\$${W[err]:-ERROR}_CMD${TAG:+2}"

Example / test:

Code:
SUCC_CMD="echo SUCC1"
SUCC_CMD2="echo SUCC2"
FAIL_CMD2="echo FAIL2"
FAIL_CMD="echo FAIL1"
ERROR_CMD="echo SNAFU"
ERROR_CMD2="echo SNAFU"

W=(SUCC FAIL)

for err in 0 1 2; do for TAG in "" 1; do  eval "\$${W[err]:-ERROR}_CMD${TAG:+2}"; done; done
SUCC1
SUCC2
FAIL1
FAIL2
SNAFU
SNAFU


Last edited by RudiC; 09-19-2018 at 08:21 AM..
# 5  
Old 09-19-2018
Quote:
Originally Posted by da1
I was thinking about a case statement but I have to evaluate $err and the value of $TAG together and I'm not sure how that would look and work. I guess something like this:

Code:
case "${err}" in
        "0")
        [ "${err}" == "0" ] && [ ! -z "${TAG}" ]
        $SUCC_CMD2
        ;;
        "1")
        [ "${err}" == "0" ] && [ ! -z "${TAG}" ]
        $FAIL_CMD2
        ;;
        *) printf "Something went wrong"
           exit 1
         ;;
esac

You have evaluated $err already so you don't need to repeat that!
I have highlighted what is always true and always false.
Your original spaghetti if-then-else-fi translated:
Code:
case $err in
0)
  if [ -n "$TAG" ];then
    $SUCC_CMD2
  else
    $SUCC_CMD
  fi
;;
*)
  if [ -n "$TAG" ];then
    $FAIL_CMD2
  else
    $FAIL_CMD
  fi
  exit 1
;; 
esac

This User Gave Thanks to MadeInGermany For This Post:
# 6  
Old 09-19-2018
damn, that's a good one, dankeschoen.


BTW, regarding this:
Code:
# form the cmd to be executed BASE_CMD="base_cmd arg1" # if err=0, append "arg2" SUCC_CMD="$BASE_CMD arg2" # if err=1, change arg2 to arg3 FAIL_CMD="${SUCC_CMD//arg2/arg3}" # if $TAG and $VALUE are set and err=0, do this: SUCC_CMD2="$SUCC_CMD $TAG $VALUE arg4" # same as above but if err=1 FAIL_CMD2="${SUCC_CMD2//arg4/arg5}"

Does it make sense to keep it like this or change it to something else?

Last edited by da1; 09-19-2018 at 10:37 AM.. Reason: fix [code]
# 7  
Old 09-19-2018
To construct variables from nother variables like
Code:
SUCC_CMD2="$SUCC_CMD $TAG $VALUE arg4"
FAIL_CMD2="${SUCC_CMD2//arg4/arg5}"

can go awfully wrong in some cases. Imaging $TAG or $VALUE contain "arg4"; is it intended to change these??
It is safer to repeat the previous
Code:
FAIL_CMD2="$SUCC_CMD $TAG $VALUE arg5"

And this will still go wrong in case $TAG or $VALUE contain a wildcard like *
Most safe is to have only one common static variable
Code:
BASE_CMD="base_cmd arg1"

and add the arguments in the branch structure:
Code:
case $err in
0)
  if [ -z "$TAG" ];then
    $BASE_CMD arg2
  else
    $BASE_CMD arg2 "$TAG" "$VALUE" arg4
  fi
;;
*)
  if [ -z "$TAG" ];then
    $BASE_CMD arg3
  else
    $BASE_CMD arg2 "$TAG" "$VALUE" arg5
  fi
  exit 1
;;
esac

And you more easily see logical errors.

Last edited by MadeInGermany; 09-19-2018 at 06:06 PM.. Reason: Added quotes around variables in command arguments
This User Gave Thanks to MadeInGermany For This Post:
Login or Register to Ask a Question

Previous Thread | Next Thread

9 More Discussions You Might Find Interesting

1. AIX

Apache 2.4 directory cannot display "Last modified" "Size" "Description"

Hi 2 all, i have had AIX 7.2 :/# /usr/IBMAHS/bin/apachectl -v Server version: Apache/2.4.12 (Unix) Server built: May 25 2015 04:58:27 :/#:/# /usr/IBMAHS/bin/apachectl -M Loaded Modules: core_module (static) so_module (static) http_module (static) mpm_worker_module (static) ... (3 Replies)
Discussion started by: penchev
3 Replies

2. Shell Programming and Scripting

Bash script - Print an ascii file using specific font "Latin Modern Mono 12" "regular" "9"

Hello. System : opensuse leap 42.3 I have a bash script that build a text file. I would like the last command doing : print_cmd -o page-left=43 -o page-right=22 -o page-top=28 -o page-bottom=43 -o font=LatinModernMono12:regular:9 some_file.txt where : print_cmd ::= some printing... (1 Reply)
Discussion started by: jcdole
1 Replies

3. UNIX for Dummies Questions & Answers

Using "mailx" command to read "to" and "cc" email addreses from input file

How to use "mailx" command to do e-mail reading the input file containing email address, where column 1 has name and column 2 containing “To” e-mail address and column 3 contains “cc” e-mail address to include with same email. Sample input file, email.txt Below is an sample code where... (2 Replies)
Discussion started by: asjaiswal
2 Replies

4. Ubuntu

What is solution for this error "tar: Exiting with failure status due to previous errors"?

Does anyone know what is solution for this error ?tar: Exiting with failure status due to previous errors from last 3 days I am trying to take backup of home/user directory getting again and again same error please anyone give me solution (8 Replies)
Discussion started by: Akshay Hegde
8 Replies

5. Solaris

The slices "usr", "opt", "tmp" disappeared!!! Help please.

The system don't boot. on the screen appears following: press enter to maintenance (or type CTRL-D to continue)...I checked with format command. ... the slices "0-root","1-swap","2-backup" exist. ...the slises "3-var","6-usr" -unassigned. :( (16 Replies)
Discussion started by: wolfgang
16 Replies

6. Shell Programming and Scripting

how to use "cut" or "awk" or "sed" to remove a string

logs: "/home/abc/public_html/index.php" "/home/abc/public_html/index.php" "/home/xyz/public_html/index.php" "/home/xyz/public_html/index.php" "/home/xyz/public_html/index.php" how to use "cut" or "awk" or "sed" to get the following result: abc abc xyz xyz xyz (8 Replies)
Discussion started by: timmywong
8 Replies

7. Shell Programming and Scripting

awk command to replace ";" with "|" and ""|" at diferent places in line of file

Hi, I have line in input file as below: 3G_CENTRAL;INDONESIA_(M)_TELKOMSEL;SPECIAL_WORLD_GRP_7_FA_2_TELKOMSEL My expected output for line in the file must be : "1-Radon1-cMOC_deg"|"LDIndex"|"3G_CENTRAL|INDONESIA_(M)_TELKOMSEL"|LAST|"SPECIAL_WORLD_GRP_7_FA_2_TELKOMSEL" Can someone... (7 Replies)
Discussion started by: shis100
7 Replies

8. Shell Programming and Scripting

cat $como_file | awk /^~/'{print $1","$2","$3","$4}' | sed -e 's/~//g'

hi All, cat file_name | awk /^~/'{print $1","$2","$3","$4}' | sed -e 's/~//g' Can this be done by using sed or awk alone (4 Replies)
Discussion started by: harshakusam
4 Replies

9. UNIX for Dummies Questions & Answers

Explain the line "mn_code=`env|grep "..mn"|awk -F"=" '{print $2}'`"

Hi Friends, Can any of you explain me about the below line of code? mn_code=`env|grep "..mn"|awk -F"=" '{print $2}'` Im not able to understand, what exactly it is doing :confused: Any help would be useful for me. Lokesha (4 Replies)
Discussion started by: Lokesha
4 Replies
Login or Register to Ask a Question