问题很简单。我想评估PS1
bash 脚本中的当前值。
谷歌上的所有材料都指向关于拉皮条的教程,但我想评估一下我当前的终端或至少在某些终端如何呈现它。
是否有任何软件/功能可以帮助我实现这一目标?当然,我希望评估所有转义字符,所以echo $PS1
在我的情况下不是那么有用。
使用参数转换提示字符串的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 ~]$
从关于Shell Parameter Expansion的Bash Reference Manual页面:
${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*
,则依次对每个位置参数应用操作,展开是结果列表。@
如果 parameter 是下标为or的数组变量*
,则依次对数组的每个成员进行运算,展开结果为列表。
(另请参阅来自重复问题Echo expand PS1的答案。)
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}"
adamhotep is dining at 11:49:01 using zsh 5.7.1
[adamhotep@tabasco ~]% print -P "$TEST_STRING"
adamhotep is dining at 11:49:07 using zsh 5.7.1
[adamhotep@tabasco ~]%
Zsh扩展和替换手册告诉我们:
参数扩展标志。如果左大括号后直接跟左括号,则匹配右括号之前的字符串将被视为标志列表。在重复标志有意义的情况下,重复不必是连续的;例如,
(q%q%q)
与更易读的意思相同(%%qqq)
。支持以下标志:
…</p>
%
%
以与提示相同的方式扩展结果单词中的 所有转义(请参阅提示扩展)。PROMPT_PERCENT
如果此标志被给出两次,则根据,PROMPT_SUBST
和PROMPT_BANG
选项的设置对结果单词进行完整的提示扩展。
来自Zsh Builtins文档print
:
-P
执行提示扩展(请参阅提示扩展)。与 结合使用时-f
,提示转义序列仅在插值参数内解析,而不在格式字符串内解析。
另一种可能性,使用script
实用程序(bsdutils
ubuntu 上的包的一部分):
$ 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>
script
命令生成指定的文件,输出也显示在标准输出上。如果省略文件名,它会生成一个名为 typescript 的文件。
由于在这种情况下我们对日志文件不感兴趣,因此将文件名指定为/dev/null
. 而是将脚本命令的标准输出传递给 awk 以进行进一步处理。
PROMPT_COMMAND
...编辑:
新版本似乎与打字稿中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=$0;} 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>
解释:
尝试在终端上手动输入这些命令。heredoc
按原样复制这些命令,然后单击鼠标中键进行粘贴。脚本命令的标准输出将包含非常相似的内容。
例如,在上述情况下,脚本命令的输出如下:
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
使用“some_random_string_here_that_is_not_part_of_PS1”作为分隔符(awk 的记录分隔符)拆分该标准输出并打印最后一条记录。
编辑2:
另一种机制(使用 bash 源代码和 gdb):
$ 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>
\[
或\]
字符串PS1
将分别打印为\1
/ \2
。你可以删除那些tr -d '\1\2' <<< "$expanded_PS1"
gdb
无法附加到进程(似乎发生在 ubuntu :-\ 中),请gdb
使用sudo
.我会这样:
echo $PS1
然后用编辑器编辑它。之后进行测试(在会话处于活动状态时设置):
PS1='\[\033[1m\]\[\033[34m\]\u\[\033[90m\]@\[\033[01;35m\]\h:\[\033[01;32m\]\W\[\033[0m\]$ '
(\u 代表用户,\h 代表主机,\w 代表完整路径,\W 代表短路径)
如果我喜欢它,我将通过更改~/.bashrc中PS1的值来使其永久化
PS:
如果要查看所有全局变量:
printenv
或者:
printenv <name_of_var_to_see>
另一种方法是eval
回应您处理任何扩展的提示(不确定为什么保留括号)。这很可能不如@anishsane 的方法稳健,但可能会更快一点:
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[@]}"
已经对这个GitHub 问题进行了修改。
试试下面的命令
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 $1'})"/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
编辑 /etc/bashrc 文件
您可以以此为例并检查输出
# 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