有没有办法可以确定提示的长度?有没有办法可以查看变量PS1
并从中获取长度并重复相同长度的字符?
我正在尝试为 bash 命令创建一个新的终端提示符。
答案1
如果你PS1
写得很好,那么它将非打印片段包含在内\[ \]
。你需要先摆脱这些片段。通常我会使用,sed
但我不认为可以很容易地用进行非贪婪匹配sed
,因此perl
:
perl -pe 's|\\\[.*?\\\]||g' <<<"$PS1"
里面的换行符\[ \]
将不会perl
删除该片段。这不应该发生写得很好PS1
,所以不是问题。
您需要辅助变量中的结果:
ps="$(perl -pe 's|\\\[.*?\\\]||g' <<<"$PS1")"
需要一个单独的变量,因为下一步是要求 Bash 评估字符串,就好像它是一个提示一样;使用变量很容易做到这一点。
但有一点:此处的字符串 ( <<<
) 添加了尾随换行符,然后命令替换 ( $( )
) 删除了全部尾随换行符。如果最初没有换行符,那么两种现象将相互抵消。如果有尾随换行符,那么您将失去所有换行符,最终结果将偏离未知数。在一般情况下,我们可以通过附加后缀(此处X
)来处理此问题:
ps="$(perl -pe 's|\\\[.*?\\\]||g' <<<"${PS1}X")"
这样两种机制肯定互相抵消。然后你可以像提示一样进行评估,如下所示:
printf '%s' "${ps@P}"
无论如何你都需要长度,所以printf
并不是完全必要的:
wc -m <<<"${ps@P}"
我认为wc -m
比这个更好wc -c
。结果被夸大了,因为我们的后缀(长度为 1)和另一个额外的换行符(来自<<<
)。因此您需要减去 2。
整个过程作为一个函数:
plen () {
local ps len
ps="$(perl -pe 's|\\\[.*?\\\]||g' <<<"${PS1}X")"
len="$(wc -m <<<"${ps@P}")"
printf '%s\n' "$((len-2))"
}
你说你想
重复相同长度的字符
也许你不需要这个长度。
pblock () {
local ps
ps="$(perl -pe 's|\\\[.*?\\\]||g' <<<"${PS1}X")"
ps="${ps@P}"
printf '%s' "${ps::-1}" | tr -c '\n\r' 'M'
}
此功能将复制提示的形状,即使它是多行的,尽管制表符之类的字符很麻烦。根据您的tr
多字节字符(例如ś
),也可能导致该功能无法按预期工作。
您可能喜欢或不喜欢printf '%s\n' …
。