Here is my new oh-my-zsh zsh-theme, updated with an escape character before each code block within $()'s which allows it to update every time the prompt is displayed (works with setopt prompt_subst:

PROMPT="%F{yellow}%n%F{white}@%F{green}%M %F{cyan}%j %F{white}\$(curl -s https://api.myip.com | jq .ip -r) %F{green}%2c%F{cyan} [%f "
RPROMPT="\$(git_prompt_info) %F{cyan}] %F{red}\$(top -l 1 | grep 'Load Avg' | awk '{print $3, $4, $5}' | tr -d , | awk '{print $2}')[\$(sysctl hw.ncpu | grep -o -E '[1-9]+')] @ \$(top -l 1 | grep 'CPU usage:' | awk '{print $3, $5, $7}' | tr -d , | awk '{print $3,"%%"}') idle %F{green}%W %* %F{yellow}%D{%p}%f"


It will dynamically change the date and time, the IP address, and the git_prompt_info, every time I press return, but the shell scripting like \$(top -l 1 | grep 'Load Avg' | awk '{print $3, $4, $5}' | tr -d , | awk '{print $2}') does not update every time I press "return", it gives me an error instead:

awk: syntax error at source line 1
 context is
    {print >>>  , <<<
awk: illegal statement at source line 1
awk: illegal statement at source line 1

What's going on here?

  • You assign RPROMPT from a double-quoted-string. This means that $1 inside will be replaced by the shell. You would have to escape the $, i.e. write \$1. Commented Aug 29, 2022 at 14:12

2 Answers 2

setopt prompt_subst

Enable prompt_subst in your zshrc or other file sourced by your shell to make zsh re-evaluate your PS1 variable on each prompt appearance.

  • I tried putting setopt prompt_subst into my .zshrc file. Nothing seemed to change. I notice you said PS1 as opposed to PROMPT and RPROMPT. What's the PS1 equivalent of the RPROMPT? Commented Nov 1, 2020 at 22:12
  • I updated my question to concern the "disobeying" evaluation of $( )'s. - after I successfully put setopt prompt_subst and the escape character \ before each $( ). Commented Nov 2, 2020 at 1:31

Your problem boils down to an assignment similar to this one:

 rp="\$(awk '{print $3, $5, $7}')"

If you try this and do a echo $rp afterwards, you see that the awk command indeed is broken. The reason is the initial backslash: Because of this, the $(....) construct does not represent a new scope and we are inside the (outer) double quotes. Therefore the shell substitutes the $-variables.

You have two possibilities:

(1) Escape the $

 rp="\$(awk '{print \$3, \$5, \$7}')"

(2) Use single quotes for the assignment. Of course this means that you can't have single quotes inside. Example:

rp='$(awk "{print $3, $5, $7}")'

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .