Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Use of $? in a bash function

I am having a problem with testing $? within a function, regardless of how it is passed.

__myretval () {
  if [ $1 -ne 0 ]; then
    printf -- "%s" "$1"
  fi
}
PS1="$(__myretval '$?') $"

The goal being to have retvals show if they not 0. The function is MUCH more detailed than this and it must be in the function, please do not suggest pulling this out of the function.

$ false
1 $ true
$

I have tried every combination I can think of, but nothing seems to work, including but not limited to combinations of the following. I've tried putting the value in quotes, and without quotes; I've tried doing the same for the 0, with quotes and without.

if [ $1 -ne 0 ]; then
if [ $1 != 0 ]; then
if [ $? -ne 0 ]; then
if [ $? != 0 ]; then
PS1="$(__myretval "$?") $"
PS1="$(__myretval "\$?") $"

Either the value always prints or it never prints.

like image 203
jnovack Avatar asked Mar 19 '23 18:03

jnovack


2 Answers

This works for me:

__myretval () {
  if (($1)); then
    printf -- "%s" "$1"
  fi
}
PS1='$(__myretval "$?") $'

It seems your problem was with the quotes.


When you state:

PS1="$(__myretval '$?') $"

what you're doing is (because of the double quotes): setting PS1 to the output of the function __myretval with the argument '$?', where $? is expanded now. So your PS1 never changes.

What you want instead is PS1 to contain the string:

$(__myretval "$?") $

so that this string is expanded (evaluated) at each new prompt. That's why you should use single quotes to define your PS1.

like image 62
gniourf_gniourf Avatar answered Apr 02 '23 01:04

gniourf_gniourf


You need to alternate the use of single ' and double " quotes to control when the contained expression and variables get evaluated.

Also, why pass $? as a parameter? Add local status=$? as the first statement in the function, and you won't need any checks:

__myretval () {
  local status=$?
  [[ $status -eq 0 ]] && return

  echo $status
}

Also, because $status is now guaranteed to contain a valid string with no surprises, we won't need printf, as $( ... ) will drop the final newline.

How you set PS1 will require appropriate quoting:

PS1="${OTHER_VARIABLE}"'$(__myretval) $ '

Double quotes evaluate when PS1 gets set, single quotes postpone that.

like image 37
Henk Langeveld Avatar answered Apr 02 '23 02:04

Henk Langeveld