20

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

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

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

4

6 回答 6

19

使用参数转换提示字符串的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_SUBSTPROMPT_BANG选项的设置对结果单词进行完整的提示扩展。

来自Zsh Builtins文档print

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

于 2019-05-23T01:45:10.743 回答
4

另一种可能性,使用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>

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

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

  1. 整个代码也可以封装成一个函数。
  2. 此外,也可以将输出提示分配给变量。
  3. 这种方法还支持解析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>
  1. 不过这里有一个小问题。中的\[\]字符串PS1将分别打印为\1/ \2。你可以删除那些tr -d '\1\2' <<< "$expanded_PS1"
  2. 如果您收到错误,例如gdb无法附加到进程(似乎发生在 ubuntu :-\ 中),请gdb使用sudo.
于 2014-03-11T11:37:56.553 回答
4

我会这样:

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>
于 2019-02-06T07:44:59.167 回答
3

另一种方法是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 问题进行了修改。

于 2017-05-20T19:54:02.757 回答
0

试试下面的命令

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
于 2014-03-12T03:59:40.980 回答
-1

编辑 /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
于 2014-03-11T10:31:06.323 回答