防止命令替换删除尾随换行符的优雅方法

防止命令替换删除尾随换行符的优雅方法

我正在自定义 zshPROMPT并调用一个函数,该函数可能是也可能不是echo基于环境变量状态的字符串:

function my_info {
    [[ -n "$ENV_VAR"]] && echo "Some useful information\n"
}

local my_info='$(my_info)'

PROMPT="${my_info}My awesome prompt $>"

我希望信息以尾随换行符结尾,这样如果设置了它,它就会显示在自己的行上:

Some useful information
My awesome prompt $>

但是,如果未设置,我希望提示符位于单行上,避免提示符中的无条件换行符导致出现空行:

PROMPT="${my_info}  # <= Don't want that :)
My awesome prompt $>"

目前,我$(command substitution)通过在换行符后添加非打印字符来解决删除换行符的问题,因此换行符不再尾随:

[[ -n "$ENV_VAR"]] && echo "Some useful information\n\r"

这显然是一个黑客行为。有没有一种干净的方法来返回以换行符结尾的字符串?

编辑:我明白是什么导致尾随换行符丢失为什么会发生这种情况,但在这个问题中我特别想知道如何防止这种行为(而且我不认为这个解决方法适用于我的情况,因为我正在寻找“条件”换行符)。

编辑:我纠正一下:参考解决方法实际上可能是一个相当不错的解决方案(因为在比较中添加前缀字符串是一种常见且有些相似的模式),但我无法让它正常工作:

echo "Some useful information\n"x
  [...]
PROMPT="${my_info%x}My awesome prompt $>"

不会x为我删除尾随。

编辑:调整建议的解决方法以解决快速扩展的怪异问题,这对我有用:

function my_info {
    [[ -n "$ENV_VAR"]] && echo "Some useful information\n"x
}

local my_info='${$(my_info)%x}'

PROMPT="$my_info My awesome prompt $>"

您可以判断这是否是比原始解决方案更好的解决方案。我认为它更明确一点,但也感觉可读性较差。

答案1

最后的换行符从命令替换中删除。即使 zsh 也没有提供避免这种情况的选项。因此,如果您想保留最终换行符,则需要将它们安排为不是最终换行符。

最简单的方法是在您想要准确获取的数据后面打印一个额外的字符(换行符除外),并从命令替换的结果中删除最后一个额外的字符。您可以选择在该额外字符后添加换行符,无论如何它都会被删除。

在 zsh 中,您可以将命令替换与字符串操作结合起来以删除多余的字符。

my_info='${$(my_info; echo .)%.}'
PROMPT="${my_info}My awesome prompt $>"

在您的场景中,请注意这my_info不是命令的输出,而是用于获取输出的 shell 片段,当提示符展开时将对其进行评估。PROMPT=${my_info%x}…不起作用,因为它尝试x从变量的值中删除最终值my_info,但它以).

在其他 shell 中,这需要分两步完成:

output=$(my_info; echo .)
output=${output%.}

在 bash 中,您不能my_info直接从调用PS1;而是需要从 调用它PROMPT_COMMAND

PROMPT_COMMAND='my_info=$(my_info; echo .)'
PS1='${my_info%.}…'

答案2

您可以让函数输出转义的转义码,以便在展开时它变成换行符。

$ function my_info {
>    [[ -n "$ENV_VAR"]] && echo 'Some useful information\\n'
>}
$ echo $(my_info)
Some useful information

$

相关内容