如何获取提示的长度?

如何获取提示的长度?

有没有办法可以确定提示的长度?有没有办法可以查看变量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' …

相关内容