2010-06-17 44 views
74

之间虽然在this awesome thread考虑看看我注意到,一些示例使用是什么PS1和PROMPT_COMMAND

PS1="Blah Blah Blah" 

有的使用

PROMPT_COMMAND="Blah Blah Blah" 

(有的同时使用)设置提示时差别在一个bash shell中。两者有什么区别? SO搜索甚至更广泛的谷歌搜索没有得到我的结果,所以即使是正确的地方寻找答案的链接,将不胜感激。谢谢!

回答

39

从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。

53

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

例如,这里是我的bash提示符同时使用PROMPT_COMMAND和PS1。 PROMPT_COMMAND中的bash代码可以确定你可能在哪个git分支中,并在提示符处显示它,以及最后一个运行进程的退出状态,pwd的主机名和基本名。变量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\[email protected]\h $BLUE\W $CYAN$BRANCH$RED$ERRMSG \$ $LIGHT_GRAY";' 

示例输出看起来像这样在非git的目录:

[email protected] Documents $ false 
[email protected] Documents 1 $ 

,并在你看到的分支名一个git目录:

[email protected] rework mybranch $ 
+1

您可以缩短其中一行:'if git branch&>/dev/null;然后\'。它将stdout和stderr重定向到/ dev/null。 http://www.tldp.org/LDP/abs/html/io-redirection.html – 2014-10-03 05:39:48

+2

没有必要* export *'PROMPT_COMMAND'。 – dolmen 2016-09-23 22:00:33

+2

我认为ceving的评论对于这个答案也是非常正确的:'不要在PROMPT_COMMAND中设置PS1!在PROMPT_COMMAND中设置变量并在PS1中使用它们。 – Blauhirn 2017-05-05 03:07:24

39

不同的是,PS1是使用的实际提示字符串,而PROMPT_COMMAND是在提示之前执行的命令。如果你想建立一个提示的最简单,最灵活的方式,试试这个:

在你的.bashrc将这个:

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

然后写一个脚本(bash中,Perl中,红宝石:你的选择),并将其放置在〜/ bin/bash_prompt中。

脚本可以使用它喜欢的任何信息来构建提示。这比IMO简单得多,因为您不必学习为PS1变量开发的巴洛克式替代语言。

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

+6

不要在'PROMPT_COMMAND'中设置'PS1'!在'PROMPT_COMMAND'中设置变量并在'PS1'中使用它们。否则,你将失去使用像'\ u'或'\ h'这样的'PS1'转义序列的能力。你必须在'PROMPT_COMMAND'中重塑它们。这可能是可能的,但不可能解决标记非打印字符开始和结尾的'\ ['和'\]'的损失。这意味着您不能在不提示终端提示长度的情况下使用颜色。当编辑一条产生两行的命令时,这会混淆“readline”。最后你在屏幕上乱七八糟。 – ceving 2015-10-16 08:26:11

+0

@ceving真的!人们可以使用PROMPT_COMMAND来改变你的PS1的**格式**并获得两全其美的好处 – cvsguimaraes 2016-03-29 05:20:43

+3

在打印PS1之前执行PROMPT_COMMAND。在'PROMPT_COMMAND'里面设置'PS1'没有问题,因为'PROMPT_COMMAND'完成后,shell会打印'PS1',它是从'PROMPT_COMMAND'修改的(或者在这里是'prompt_command'内)? – 2016-08-31 06:10:20

7

man bash

PROMPT_COMMAND

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

PS1

该参数的值被扩展(见下文PROMPTING)和用作主提示字符串。默认值是''\ s- \ v \ $''。

如果你只是想设置提示字符串,单独使用PS1是不够的:

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

如果你只想打印提示之前做别的事情,用PROMPT_COMMAND。例如,如果要将缓存的写入同步到磁盘,可写入:

PROMPT_COMMAND='sync' 
+1

您也可以在不需要'PROMPT_COMMAND'的情况下从'PS1'设置终端的标题,因为设置标题的顺序可以包含在用'\ ['和'\]'包装的'PS1'中。 – dolmen 2016-09-23 22:07:30

+1

@dolmen好的。然后让我们做一些其他的事情,比如动态设置一个环境变量。 – Cyker 2016-09-29 16:25:05