Hamid Bazargani Hamid Bazargani - 6 months ago 9
Bash Question

Update variable in bash function and use it in prompt (PS1)

What I want to do is to call a function in

PS1
to update a variable inside the function. Then I like to use that variable to add another line to PS1. Like bellow:

my_func(){
var="_RED_"
echo "hello in red"
}
PS1="\[\033]0;\w\007\]"
PS1+='$(my_func)'
if [ $var = "_RED_" ]; then # here I want to use that var
PS1+="\[$(tput setaf 124)\] red"
fi


The reason for doing this is to bring non-printable characters
\[
and
\]
out of the function to prevent from overlapping long lines that is caused by
\[ \]

Answer

What I want to do is to call a function in PS1 to update a variable inside the function. Then I like to use that variable to add another line to PS1.

From your sample code, I suppose you mean that you want to perform a command expansion involving a shell function in the process of assigning a value to PS1. It is important in that case to recognize that that the command expansion will be performed once, at the time the value of PS1 is set / modified, not each time PS1 is displayed. Your wording and specific syntax make me suspect that you have a different expectation.

Consider this part of your code:

PS1="\[\033]0;\w\007\]"
PS1+='$(my_func)'

Because it appears in single quotes, the $(my_func) is not subject to command expansion or any other expansion. Although the single quotes are removed before the value is appended to PS1, that does not mean it will be subject to expansion later.

Now, because the function body is a curly-braced compound command, if it were executed then it would indeed set the value of var in the current shell, and that effect would be visible after the function returns. But,

  1. again, nothing in the code you presented results in your function ever being called, and
  2. even if it were called, you test for a value of $var different from the one your function would set.

In contrast, consider this other fragment of your code:

PS1+="\[$(tput setaf 124)\] red"

Because the whole string is double-quoted in this case, the contents are subject to command expansion, so if this were executed, the $(tput setaf 124) would be replaced with the output from running tput setaf 124. But again, that would happen at the time that PS1's value is modified, not every time its value is displayed.