Fel*_*sen 27 bash command-line ps1
我确信我已经看到有人在他们的终端窗口中将提示的一部分对齐到右侧,然后将实际的光标从第二行开始。我知道我可以在 PS1 中用 "\n" 实现第二行,但我不知道如何将它的一部分向右对齐。我看到的只是在两个字符串之间添加了空格吗?
nic*_*kl- 29
根据我在这里找到的信息,我能够找到一种更简单的右对齐解决方案,同时在右侧或左侧容纳可变长度的内容,包括对颜色的支持。为方便起见,在此添加...
关于颜色的注意事项:使用\033有利于替代品的转义符,没有\[\]分组,证明最兼容,因此推荐。
诀窍是先写右边,然后使用回车(\r)返回到行首并继续覆盖左边的内容,如下所示:
prompt() {
PS1=$(printf "%*s\r%s\n\$ " "$(tput cols)" 'right' 'left')
}
PROMPT_COMMAND=prompt
Run Code Online (Sandbox Code Playgroud)
我tput cols在 Mac OS X 上使用来检索终端/控制台宽度,terminfo因为我的$COLUMNSvar 未填充,env但您可以通过提供“ ”或您喜欢的任何其他值来替换可替换的“ *”值。%*s${COLUMNS}
下一个示例用于$RANDOM生成不同长度的内容,包括颜色并展示如何提取函数以将实现重构为可重用函数。
function prompt_right() {
echo -e "\033[0;36m$(echo ${RANDOM})\033[0m"
}
function prompt_left() {
echo -e "\033[0;35m${RANDOM}\033[0m"
}
function prompt() {
compensate=11
PS1=$(printf "%*s\r%s\n\$ " "$(($(tput cols)+${compensate}))" "$(prompt_right)" "$(prompt_left)")
}
PROMPT_COMMAND=prompt
Run Code Online (Sandbox Code Playgroud)
由于printf假设字符串的长度是我们需要补偿渲染颜色所需的字符数量的字符数,您会发现它总是短于屏幕末尾,因为没有补偿的非打印 ANSI 字符。颜色所需的字符保持不变,您会发现 printf 也考虑了长度的变化,如$RANDOMexample'返回的那样,这使我们的正确对齐保持一致。
但是,特殊的 bash 提示转义序列(即\u, \w, \h, \t)不是这种情况,因为它们只会记录长度为 2,因为 bash 只会在显示提示时翻译它们,在 printf 呈现字符串之后。这不会影响左侧,但最好避免它们在右侧。
如果生成的内容将保持恒定长度,则无关紧要。与 time\t选项一样,它将始终呈现相同数量的字符 (8) 24 次。在这些情况下,我们只需要考虑为适应所计算的 2 个字符之间的差异所需的补偿,这导致打印时为 8 个字符。
请记住,您可能需要对\\\某些转义序列进行三次转义,否则这些转义序列对字符串具有意义。与以下示例一样,当前工作目录转义\w没有任何其他意义,因此它按预期工作,但 time \t,这意味着制表符,如果不首先对其进行三次转义,则无法按预期工作。
function prompt_right() {
echo -e "\033[0;36m\\\t\033[0m"
}
function prompt_left() {
echo -e "\033[0;35m\w\033[0m"
}
function prompt() {
compensate=5
PS1=$(printf "%*s\r%s\n\$ " "$(($(tput cols)+${compensate}))" "$(prompt_right)" "$(prompt_left)")
}
PROMPT_COMMAND=prompt
Run Code Online (Sandbox Code Playgroud)
快乐!
Gil*_*il' 18
通过在显示提示之前显示第一行,可以很容易地完成您想要的操作。例如,下面\w在第一行左边显示一个提示,在第一行右边显示一个提示\u@\h。它利用$COLUMNS包含终端宽度的变量和$PROMPT_COMMAND在 bash 显示提示之前评估的参数。
print_pre_prompt ()
{
PS1L=$PWD
if [[ $PS1L/ = "$HOME"/* ]]; then PS1L=\~${PS1L#$HOME}; fi
PS1R=$USER@$HOSTNAME
printf "%s%$(($COLUMNS-${#PS1L}))s" "$PS1L" "$PS1R"
}
PROMPT_COMMAND=print_pre_prompt
Run Code Online (Sandbox Code Playgroud)
小智 8
使用printfwith$COLUMNS效果很好,例如:
printf "%${COLUMNS}s\n" "hello"
Run Code Online (Sandbox Code Playgroud)
它对我来说完全正确。
以下将在终端的 RHS 上以红色显示当前日期和时间。
# Create a string like: "[ Apr 25 16:06 ]" with time in RED.
printf -v PS1RHS "\e[0m[ \e[0;1;31m%(%b %d %H:%M)T \e[0m]" -1 # -1 is current time
# Strip ANSI commands before counting length
# From: https://www.commandlinefu.com/commands/view/12043/remove-color-special-escape-ansi-codes-from-text-with-sed
PS1RHS_stripped=$(sed "s,\x1B\[[0-9;]*[a-zA-Z],,g" <<<"$PS1RHS")
# Reference: https://en.wikipedia.org/wiki/ANSI_escape_code
local Save='\e[s' # Save cursor position
local Rest='\e[u' # Restore cursor to save point
# Save cursor position, jump to right hand edge, then go left N columns where
# N is the length of the printable RHS string. Print the RHS string, then
# return to the saved position and print the LHS prompt.
# Note: "\[" and "\]" are used so that bash can calculate the number of
# printed characters so that the prompt doesn't do strange things when
# editing the entered text.
PS1="\[${Save}\e[${COLUMNS:-$(tput cols)}C\e[${#PS1RHS_stripped}D${PS1RHS}${Rest}\]${PS1}"
Run Code Online (Sandbox Code Playgroud)
好处:
shellcheck干净的。.inputrc有set show-mode-in-prompt on.\[and中,\]以便在提示处输入的编辑文本不会导致提示异常重印。注意:您需要确保$PS1在此代码执行之前的任何颜色序列都正确包含在其中\[并且\]没有嵌套。