如何打印当前的 bash 提示?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/22322879/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-18 09:52:36  来源:igfitidea点击:

How to print current bash prompt?

bashpromptps1

提问by Piotr Zierhoffer

The question is simple. I want to evaluate current value of PS1in my bash script.

问题很简单。我想评估PS1我的 bash 脚本中的当前值。

All materials on google point to tutorials on pimping it up, but I want to evaluate to see how would it be rendered by my current terminal, or at least by someterminal.

谷歌上的所有材料都指向有关拉皮条的教程,但我想评估一下我当前的终端或至少某个终端将如何呈现它。

Is there any soft/function that would help me achieve that? Of course I'd like to have all escaped characters evaluated, so echo $PS1is not that useful in my case.

是否有任何软/功能可以帮助我实现这一目标?当然,我希望评估所有转义字符,因此echo $PS1在我的情况下不是那么有用。

采纳答案by Adam Katz

Bash 4.4+ solutionusing parameter transformation for a prompt string: echo "${PS1@P}"

使用参数转换的Bash 4.4+ 解决方案提示字符串:echo "${PS1@P}"

[adamhotep@tabasco ~]$ echo "the prompt is '${PS1@P}'"
the prompt is '[adamhotep@tabasco ~]$'
[adamhotep@tabasco ~]$ TEST_STRING='\u is dining at \t using \s \V'
[adamhotep@tabasco ~]$ echo "${TEST_STRING}"
\u is dining at \t using \s \V
[adamhotep@tabasco ~]$ echo "${TEST_STRING@P}"
adamhotep is dining at 21:45:10 using bash 5.0.3
[adamhotep@tabasco ~]$ 

From the Bash Reference Manualpage on Shell Parameter Expansion:

从关于Shell Parameter ExpansionBash 参考手册页面:

${parameter@operator}

Parameter transformation. The expansion is either a transformation of the value of parameter or information about parameter itself, depending on the value of operator.
Each operator is a single letter:

Q    The expansion is a string that is the value of parameter quoted in a
     format that can be reused as input.
E    The expansion is a string that is the value of parameter with backslash
     escape sequences expanded as with the $'...' quoting mechanism.
P    The expansion is a string that is the result of expanding the value of
     parameter as if it were a prompt string (see PROMPTING below).
A    The expansion is a string in the form of an assignment statement or
     declare command that, if evaluated, will recreate parameter with its
     attributes and value.
a    The expansion is a string consisting of flag values representing
     parameter's attributes.

If parameter is @or *, the operation is applied to each positional parameter in turn, and the expansion is the resultant list. If parameter is an array variable subscripted with @or *, the operation is applied to each member of the array in turn, and the expansion is the resultant list.

${parameter@operator}

参数变换。扩展要么是参数值的变换,要么是参数本身的信息,这取决于运算符的值。
每个运算符都是一个字母:

Q    The expansion is a string that is the value of parameter quoted in a
     format that can be reused as input.
E    The expansion is a string that is the value of parameter with backslash
     escape sequences expanded as with the $'...' quoting mechanism.
P    The expansion is a string that is the result of expanding the value of
     parameter as if it were a prompt string (see PROMPTING below).
A    The expansion is a string in the form of an assignment statement or
     declare command that, if evaluated, will recreate parameter with its
     attributes and value.
a    The expansion is a string consisting of flag values representing
     parameter's attributes.

如果参数为@*,则依次对每个位置参数进行运算,展开为结果列表。如果 parameter 是一个以@or*为下标的数组变量,则依次对数组的每个成员进行运算,展开为结果列表。

(See also this answerfrom duplicate question Echo expanded PS1.)

(另请参阅重复问题Echo 扩展 PS1 中的这个答案。)

 

 

Z Shell(zsh) can do this with ${(%%)PS1}or with its printbuiltin's -Pflag:

Z Shell( zsh) 可以使用${(%%)PS1}或使用其print内置-P标志执行此操作:

[adamhotep@tabasco ~]% echo "the prompt is '${(%%)PS1}'"
the prompt is '[adamhotep@tabasco ~]%'
[adamhotep@tabasco ~]% print -P "the prompt is '$PS1'"
the prompt is '[adamhotep@tabasco ~]%'
[adamhotep@tabasco ~]% TEST_STRING="%n is dining at %* using %N $ZSH_VERSION"
[adamhotep@tabasco ~]% echo "$TEST_STRING"
%n is dining at %* using %N 5.7.1
[adamhotep@tabasco ~]% echo "${(%%)TEST_STRING}"
adkatz is dining at 11:49:01 using zsh 5.7.1
[adamhotep@tabasco ~]% print -P "$TEST_STRING"
adkatz is dining at 11:49:07 using zsh 5.7.1
[adamhotep@tabasco ~]% 

The Zsh Expansion and Subsitutionmanual tells us:

岩组扩展和Subsitution手册告诉我们:

Parameter Expansion Flags. If the opening brace is directly followed by an opening parenthesis, the string up to the matching closing parenthesis will be taken as a list of flags. In cases where repeating a flag is meaningful, the repetitions need not be consecutive; for example, (q%q%q)means the same thing as the more readable (%%qqq). The following flags are supported:

%? ?Expand all %escapes in the resulting words in the same way as in prompts (see Prompt Expansion). If this flag is given twice, full prompt expansion is done on the resulting words, depending on the setting of the PROMPT_PERCENT, PROMPT_SUBSTand PROMPT_BANGoptions.

参数扩展标志。如果左大括号后面直接跟一个左括号,则匹配右括号之前的字符串将被视为标志列表。在重复标志有意义的情况下,重复不需要是连续的;例如,(q%q%q)与更易读的意思相同(%%qqq)。支持以下标志:
...

%? ?%以与提示相同的方式展开结果单词中的所有转义符(请参阅提示展开)。如果此标志给出两次,则根据PROMPT_PERCENTPROMPT_SUBSTPROMPT_BANG选项的设置对结果词进行完整的提示扩展。

From the Zsh Builtinsdocumentation for print:

Zsh Builtins文档中print

-P? ?Perform prompt expansion (see Prompt Expansion). In combination with -f, prompt escape sequences are parsed only within interpolated arguments, not within the format string.

-P? ? 执行提示扩展(见提示扩展)。与 结合使用-f,提示转义序列仅在插值参数中解析,而不在格式字符串中解析。

回答by anishsane

One more possibility, using scriptutility (part of bsdutilspackage on ubuntu):

另一种可能性,使用script实用程序(bsdutilsubuntu 上的包的一部分):

$ TEST_PS1="\e[31;1m\u@\h:\n\e[0;1m$ \e[0m"
$ RANDOM_STRING=some_random_string_here_that_is_not_part_of_PS1
$ script /dev/null <<-EOF | awk 'NR==2' RS=$RANDOM_STRING
PS1="$TEST_PS1"; HISTFILE=/dev/null
echo -n $RANDOM_STRING
echo -n $RANDOM_STRING
exit
EOF
<prints the formatted prompt properly here>

scriptcommand generates a file specified & the output is also shown on stdout. If filename is omitted, it generates a file called typescript.

script命令生成指定的文件,输出也显示在标准输出上。如果省略 filename,它会生成一个名为 typescript 的文件。

Since we are not interested in the log file in this case, filename is specified as /dev/null. Instead the stdout of the script command is passed to awk for further processing.

由于在这种情况下我们对日志文件不感兴趣,因此将文件名指定为/dev/null. 而是将脚本命令的标准输出传递给 awk 进行进一步处理。

  1. The entire code can also be encapsulated into a function.
  2. Also, the output prompt can also be assigned to a variable.
  3. This approach also supports parsing of PROMPT_COMMAND...
  1. 整个代码也可以封装成一个函数。
  2. 此外,输出提示也可以分配给变量。
  3. 这种方法还支持解析PROMPT_COMMAND...

EDIT:
It appears that the new version of scriptechoes the piped stdinin the typescript. To handle that, the above mechanism can be changed to:

编辑:
新版本似乎与打字稿中script的管道相呼应stdin。为了解决这个问题,可以将上述机制更改为:

$ TEST_PS1="\e[31;1m\u@\h:\n\e[0;1m$ \e[0m"
$ RANDOM_STRING=some_random_string_here_that_is_not_part_of_PS1
$ script /dev/null <<-EOF | awk '{old=current; current=
PS1="\e[31;1m\u@\h:\n\e[0;1m$ \e[0m"; HISTFILE=/dev/null
alias some_random_string_here_that_is_not_part_of_PS1=true
some_random_string_here_that_is_not_part_of_PS1
some_random_string_here_that_is_not_part_of_PS1
 \e[0m"; HISTFILE=/dev/nullhsane-dev : ~/Desktop $ PS1="\e[31;1m\u@\h:\n\e[0;1m$ 
anishsane@anishsane-dev:
$ alias some_random_string_here_that_is_not_part_of_PS1=true
anishsane@anishsane-dev:
$ some_random_string_here_that_is_not_part_of_PS1
anishsane@anishsane-dev:
$ some_random_string_here_that_is_not_part_of_PS1
anishsane@anishsane-dev:
$ exit
;} END{print old}' RS=$RANDOM_STRING PS1="$TEST_PS1"; HISTFILE=/dev/null alias $RANDOM_STRING=true $RANDOM_STRING $RANDOM_STRING EOF <prints the formatted prompt properly here>

Explanation:

解释:

Try entering these commands manually on the terminal. Copy these commands under the heredocas they are and paste with mouse middle click. The script command's stdout would contain something very similar.

尝试在终端上手动输入这些命令。按heredoc原样复制这些命令,然后单击鼠标中键进行粘贴。脚本命令的标准输出将包含非常相似的内容。

e.g. With above case, the output of the script command gives this:

例如在上面的情况下,脚本命令的输出给出了这个:

$ gdb -batch -p $$ -ex 'call bind_variable("expanded_PS1", decode_prompt_string (get_string_value ("PS1")), 0)'
$ echo "$expanded_PS1"
<prints the formatted prompt properly here>

Split that stdout with "some_random_string_here_that_is_not_part_of_PS1" as delimiter (record separator of awk) and print the last but one record.

使用“some_random_string_here_that_is_not_part_of_PS1”作为分隔符(awk 的记录分隔符)拆分该标准输出并打印最后一条记录。

EDIT2:

编辑2:

Another mechanism (using bash source code and gdb):

另一种机制(使用bash源代码和gdb):

show-prompt() {
    eval 'echo -en "'$PS1'"' | sed -e 's#\\[##g' -e 's#\\]##g'
}
# To show it in a function registered with `complete -F` on
# a single tab, and keep the user's input:
show-prompt
echo -n "${COMP_WORDS[@]}"
  1. There is a tiny issue here though. The \[or \]strings in PS1will get printed as \1/\2respectively. You can remove those with tr -d '\1\2' <<< "$expanded_PS1"
  2. If you get error like gdbfailed to attach to the process (seems to happen in ubuntu :-\ ), run gdbwith sudo.
  1. 不过这里有一个小问题。中的\[\]字符串PS1将分别打印为\1/ \2。你可以删除那些tr -d '\1\2' <<< "$expanded_PS1"
  2. 如果您收到诸如gdb无法附加到进程之类的错误(似乎发生在 ubuntu :-\ 中),请gdb使用sudo.

回答by Eric Cousineau

Another way to do this would be to evalechoing your prompt to handle any expansion (was not sure why the brackets remain). This is most likely less robust than @anishsane's method, but may be a little quicker:

另一种方法是eval回应您的提示以处理任何扩展(不确定为什么保留括号)。这很可能不如@anishsane 的方法健壮,但可能会快一点:

echo $PS1

Had tinkered with that regarding this GitHub issue.

已经对这个GitHub 问题进行了修改

回答by NFSpeedy

I would get it like this:

我会像这样得到它:

PS1='\[3[1m\]\[3[34m\]\u\[3[90m\]@\[3[01;35m\]\h:\[3[01;32m\]\W\[3[0m\]$ '

And then edit it with an editor. After that for the test (this is set while the session is active):

然后用编辑器编辑。之后进行测试(这是在会话处于活动状态时设置的):

printenv

(\u is for user, \h is for host, \w is for full path and \W is for short path)

(\u 代表用户,\h 代表主机,\w 代表完整路径,\W 代表短路径)

And if I like it I will make it permanent by changing the value of PS1in ~/.bashrc

如果我喜欢它,我会让它永久改变的值PS1〜/ .bashrc中

P.S.:

PS:

If you want to see all global variables:

如果要查看所有全局变量:

printenv <name_of_var_to_see>

OR:

或者:

echo $PS1 | 
sed -e s/'\d'/"$(date +'%a %b %_d')"/g | 
sed -e s/'\t'/"$(date +'%T')"/g | 
sed -e s/'\@'/"$(date +'%r')"/g | 
sed -e s/'\T'/"$(date +'%r'| awk {'print '})"/g | 
sed -e s/'\e'//g | sed -e s/'\h'/"$HOSTNAME"/g | 
sed -e s/'\h'/"$HOSTNAME"/g | 
sed -e s/'\H'/"$HOSTNAME"/g | 
sed -e s/'\u'/"$USER"/g | 
sed -e s@'\W'@"$(pwd)"@g | 
sed -e s/'\w'/"$(pwd | sed -e s@$HOME@'~'@g )"/g | 
sed -e s/"\\"//g | 
sed -e s/"\["//g | 
sed -e s/"\]"/*/g | 
cut -d'*' -f2 | 
cut -d';' -f2 | 
sed s/\ //g | 
sed -e s/[a-z]$/"$([ "$USER" != "root" ] && echo $ || echo \#)"/g

回答by iamsrijon

Try the below command

试试下面的命令

    # If id command returns zero, you've root access.
if [ $(id -u) -eq 0 ];
then # you are root, set red colour prompt
  PS1="\[$(tput setaf 1)\]\u@\h:\w #\[$(tput sgr0)\]"
else # normal
  PS1="[\u@\h:\w] $"
fi

回答by Adrian

Edit the /etc/bashrc file

编辑 /etc/bashrc 文件

you can use this as example and check the output

您可以以此为例并检查输出

##代码##