PS1和PROMPT_COMMAND之间有什么区别

时间:2010-06-17 01:27:30

标签: bash prompt

在看this awesome thread时,我注意到一些例子使用

PS1="Blah Blah Blah"

和一些使用

PROMPT_COMMAND="Blah Blah Blah"
在bash shell中设置提示时,

(有些人同时使用)。两者有什么区别? SO搜索甚至更广泛的谷歌搜索都没有得到我的结果,所以即使找到正确的地方寻找答案的链接将不胜感激。

6 个答案:

答案 0 :(得分:63)

PROMPT_COMMAND可以包含普通的bash语句,而PS1变量也可以在变量中包含特殊字符,例如'\ h'作为主机名。

例如,这是我的bash提示符,它同时使用PROMPT_COMMAND和PS1。 PROMPT_COMMAND中的bash代码计算出你可能在的git分支,并在提示符下显示,以及最后一个运行进程的退出状态,pwd的主机名和basename。变量RET存储最后执行的程序的返回值。这很容易看出是否有错误和我在终端中运行的最后一个程序的错误代码。注意外部'围绕整个PROMPT_COMMAND表达式。它包括PS1,以便每次评估PROMPT_COMMAND变量时都会重新评估此变量。

PROMPT_COMMAND='RET=$?;\
  BRANCH="";\
  ERRMSG="";\
  if [[ $RET != 0 ]]; then\
    ERRMSG=" $RET";\
  fi;\
  if git branch &>/dev/null; then\
    BRANCH=$(git branch 2>/dev/null | grep \* |  cut -d " " -f 2);\
  fi;
PS1="$GREEN\u@\h $BLUE\W $CYAN$BRANCH$RED$ERRMSG \$ $LIGHT_GRAY";'

示例输出在非git目录中如下所示:

sashan@dhcp-au-122 Documents  $ false
sashan@dhcp-au-122 Documents  1 $ 

并在git目录中看到分支名称:

sashan@dhcp-au-122 rework mybranch $ 

更新

在阅读了评论和鲍勃的回答后,我认为按照他所描述的那样写作更好。它比我上面写的更容易维护,其中PS1变量在PROMPT_COMMAND中设置,PROMPT_COMMAND本身是一个超级复杂的字符串,在运行时由bash计算。它有效,但它比它需要的更复杂。为了公平起见,我在大约10年前为自己写了PROMPT_COMMAND,它起作用了,并没有过多考虑它。

对于那些对我如何修改我的东西感到好奇的人,我基本上把PROMPT_COMMAND的代码放在单独的文件中(如Bob描述的那样),然后回显我打算成为PS1的字符串:

GREEN="\[\033[0;32m\]"
CYAN="\[\033[0;36m\]"
RED="\[\033[0;31m\]"
PURPLE="\[\033[0;35m\]"
BROWN="\[\033[0;33m\]"
LIGHT_GRAY="\[\033[0;37m\]"
LIGHT_BLUE="\[\033[1;34m\]"
LIGHT_GREEN="\[\033[1;32m\]"
LIGHT_CYAN="\[\033[1;36m\]"
LIGHT_RED="\[\033[1;31m\]"
LIGHT_PURPLE="\[\033[1;35m\]"
YELLOW="\[\033[1;33m\]"
WHITE="\[\033[1;37m\]"
RESTORE="\[\033[0m\]" #0m restores to the terminal's default colour

if [ -z $SCHROOT_CHROOT_NAME ]; then
    SCHROOT_CHROOT_NAME=" "
fi
BRANCH=""
ERRMSG=""
RET=$1
if [[ $RET != 0 ]]; then
    ERRMSG=" $RET"
fi
if which git &>/dev/null; then
    BRANCH=$(git branch 2>/dev/null | grep \* |  cut -d " " -f 2)
else
    BRANCH="(git not installed)"
fi
echo "${GREEN}\u@\h${SCHROOT_CHROOT_NAME}${BLUE}\w \
${CYAN}${BRANCH}${RED}${ERRMSG} \$ $RESTORE"

和我的.bashrc

function prompt_command {
    RET=$?
    export PS1=$(~/.bash_prompt_command $RET)
}
PROMPT_DIRTRIM=3
export PROMPT_COMMAND=prompt_command

答案 1 :(得分:51)

来自GNU Bash文档页面:http://www.gnu.org/software/bash/manual/bashref.html

PROMPT_COMMAND
    If set, the value is interpreted as a command to execute before
    the printing of each primary prompt ($PS1).

我从未使用它,但是当我只有sh时,我本可以用它。

答案 2 :(得分:44)

区别在于PS1是使用的实际提示字符串,PROMPT_COMMAND是在提示之前执行的命令。如果您想要最简单,最灵活的方法来构建提示,请尝试以下方法:

将它放在你的.bashrc中:

function prompt_command {
  export PS1=$(~/bin/bash_prompt)
}
export PROMPT_COMMAND=prompt_command

然后编写一个脚本(bash,perl,ruby:您的选择),并将其放在〜/ bin / bash_prompt中。

脚本可以使用它喜欢的任何信息来构建提示。这是一个更简单的IMO,因为您不必学习仅为PS1变量开发的有些巴洛克式替换语言。

您可能认为只需将PROMPT_COMMAND直接设置为〜/ bin / bash_prompt,并将PS1设置为空字符串即可。这开始似乎有效,但您很快发现readline代码期望PS1设置为实际提示,并且当您在历史记录中滚动后缀时,事情就会变得混乱。此解决方法使PS1始终反映最新提示(因为该函数设置了shell的调用实例使用的实际PS1),这使得readline和命令历史记录正常工作。

答案 3 :(得分:9)

来自man bash

  

PROMPT_COMMAND

     

如果设置,则在发出每个主要提示之前将该值作为命令执行。

     

PS1

     

扩展此参数的值(请参阅下面的PROMPTING)并将其用作主要提示字符串。默认值为'' \ s- \ v \ $''。

如果您只想设置提示字符串,仅使用PS1即可:

PS1='user \u on host \h$ '

如果您想在打印提示之前执行其他操作,请使用PROMPT_COMMAND。例如,如果要将缓存写入同步到磁盘,则可以编写:

PROMPT_COMMAND='sync'

答案 4 :(得分:0)

不同之处在于

  • 如果您从PROMPT_COMMAND输出了不完整的行,这将使bash提示出错
  • PS1替代\H和朋友
  • PROMPT_COMMAND运行其内容,PS1使用其内容作为提示。

PS1在每次提示时进行变量扩展和命令替换,无需使用PROMPT_COMMANDPS1分配值或运行任意代码。您可以轻松地在{{1}中进行一次export PS1='$(uuidgen) $RANDOM',只需使用单引号

答案 5 :(得分:0)

是的,所以要尝试真正确定这一点:

  • PROMPT_COMMAND是方便使用的 bash 便利变量/功能,但是严格来说,有没有单独使用PS1不能完成的事情,对吗?

我的意思是,如果要在提示范围之外设置 另一个变量:根据外壳,可能需要首先在{{ 1}}或(最坏的情况),人们可能不得不花一些时间在调用$PS1之前在FIFO上等待(然后在$PS1的末尾重新武装); $PS1 \u可能会引起一些麻烦,尤其是在您使用一些花哨的正则表达式时;但除此之外:通过使用\h中的命令替换(甚至在特殊情况下,可以使用显式子外壳),PROMPT_COMMAND可以完成任何事情吗?

对吗?

相关问题