0

I'm having a weird situation where when I run a conditional check against a function return inside a print statement, the global variable that is set in the function does not want to work. Let me give the example:

function VALIDATE()
{
        BLAH BLAH BLAH
        ERROR="IT FAILED"
        return 0
}

######## Start relevant code ########
printf "%-50s %10s\n" " Validating and sanitizing input..." "$(if VALIDATE $HOST; then echo "[$RED  FAIL  $RESET]"; else echo "[$GREEN   OK   $RESET]"; fi)"
if [ -z $ERROR ]; then
        echo $ERROR
else
        echo "YAHOO IT WORKS"
fi

Something about running the function check inside the printf statement prevent $ERROR from being passed successfully. If for example I remove the formatting created by printf and rerun the code, ERROR works as expected.

Running the function inside the printf was initially necessary to facilitate the question answer type formatting of the output. Yes it is possible to rewrite this such that the fnction is called outside the printf statement, but this will require extra code, and I wanted to see if it could be made to work first using this short hand method. Any suggestions? Thank you!

2
  • In the example you show, the string Validating and sanitizing input.. is printed after the VALIDATE function is run.... Commented Feb 15, 2019 at 19:51
  • procedural programming should reduce your dependency on global variables for state. Commented Feb 15, 2019 at 21:10

1 Answer 1

1

Command substitution $( ... ) runs the command in a subshell. So when you change the environment inside the subshell the changes will not be visible outside.

x=1
$( x=2 )
echo $x # will print 1

@edit

I wouldn't advise for passing the errors in such fashion. You could use a temporary file / pipe to write the message to or use a custom file descriptor, but it's not really worth it and you will end up in unreadable and probably un-maintainable script. The problem with your printf is that the string Validating and sanitizing input. is printed after the VALIDATE function is run, so it's kind of strange to print it at all... Usually commands return nonzero exit status and print something to stderr on errors. It looks like you want to replicate the status line from rc-scripts.

VALIDATE() {
    if false; then
        echo "valid"
    else
        echo "IT FAILED" >&2
        return 1
    fi
}

# First notify the user we are validating the input
printf "%-50s" " Validating and sanitizing input..."
# then validate input
if validate_error=$(VALIDATE 2>&1); then
    printf "$GREEN%10s$RESET\n" "[   OK   ]"
    echo "YAHOO IT WORKS"
else
    printf "$RED%10s$RESET\n"   "[  FAIL  ]"
    echo "$validate_error"
fi

and you could wrap that in a function and pass the command as arguments:

run() {
    local errorstr
    # First notify the user we are validating the input
    printf "%-50s" "${1}..."
    shift
    if errorstr=$("$@" 2>&1); then
        printf "$GREEN%10s$RESET\n" "[   OK   ]"
    else
        printf "$RED%10s$RESET\n"   "[  FAIL  ]"
        echo "$errorstr"
    fi    
}

run "Validating and sanitizing input" VALIDATE
Sign up to request clarification or add additional context in comments.

4 Comments

I had a hunch this was the reason. Is there a way to retrieve the variable from the sub shell?
I went ahead and just re-coded it call the function outside the sub shell. Figured out a way to still keep number of lines down too. Thanks for the help!
VALIDATE $HOST; printf "%-50s %10s\n" " Validating and sanitizing input..." "$(if [ -z "$ERROR" ]; then echo "[$GREEN OK $RESET]"; else echo "[$RED FAIL $RESET] - $ERROR"; fi)"
Better yet, have VALIDATE return an appropriate error code instead of writing it to standard output. Then if VALIDATE; then ...; else status=$?; ...; fi. status` will contain the exit status of VALIDATE, and there is no longer any need to run VALIDATE in a subprocess.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.