![如何在 zsh 中使用字符串修饰符修改输入变量?](https://linux22.com/image/177928/%E5%A6%82%E4%BD%95%E5%9C%A8%20zsh%20%E4%B8%AD%E4%BD%BF%E7%94%A8%E5%AD%97%E7%AC%A6%E4%B8%B2%E4%BF%AE%E9%A5%B0%E7%AC%A6%E4%BF%AE%E6%94%B9%E8%BE%93%E5%85%A5%E5%8F%98%E9%87%8F%EF%BC%9F.png)
我一直在开发一个bold
函数作为概念验证和对自己的挑战。我正在尝试输入文本(例如foo
)并将其打印到标准输出,因为它是粗体对应项(foo
)。
语境:
我一直在使用主题文件中的变量echo
并将其作为基础。PROMPT
我没有使用任何框架。
%B%n%b
该主题使用诸如粗体用户名 ( ) 之类的代码%n
,但我不知道如何用%n
用户输入 ( $1
) 替换它。有帮助吗?
编辑:尝试的代码
echo '%B'"$1"'%b'
-在不同位置尝试过带引号和不带引号,以及使用子 shell ( {}
)
答案1
%B
和%b
是例子提示序列,通常只能用于格式化提示。对于正常的脚本编写,您可以使用以下tput
命令来实现您想要的:
echo "$(tput bold)$1$(tput sgr0)"
或者,您可以输出ECMA-48(“ANSI”)直接转义码。但我不推荐这样做,因为它跨终端的便携性较差。 (如今在 21 世纪,遇到不实现 ECMA-48 和基本 ECMA-48 SGR 功能(如粗体)的终端是相当困难的,但既然你正在挑战自己学习这一点,你应该知道终端可以不能保证理解彼此完全相同的控制序列。您还应该了解到,仍然有一些终端模拟器中的粗体是颜色变化而不是字体粗细变化。)
echo $'\e[1m'"$1"$'\e[22m'
注意使用科恩式引用为控制序列。在一般情况下,该echo
命令可能会也可能不会本身如果不是 Korn 风格的引用,则解释\e
序列,并且此类转义序列在不同的 shell 甚至同一 shell 的不同版本中工作方式不同;相反,并非所有 shell 都能理解 Korn 风格的引用。看 ”为什么 printf 比 echo 更好?对于整个故事,echo
如果您要解决除单个特定(版本)shell 之外的任何问题,那么为什么不是一个好主意。
printf '\e[1m%s\e[22m' "$1"
请注意,SGR 0(对应于\e[0m
,这tput sgr0
也是现在通常发出的)关闭一切,如果您是这样,这可能不是您想要的还使用下划线、斜体、颜色、反向视频或其他图形再现。关闭粗体具体来说,SGR 22 是图形呈现代码,它关闭粗体和淡化,恢复“中等”字体粗细。 (这S等G拉菲克右endition 控制序列允许您设置四种字体粗细:粗体、半粗体、中等和浅色。)
自从你是使用 Z shell,您可以还使用它自己的内置print
命令而不是使用echo
或printf
根本不使用。可以让内置函数print
理解 Z shell 提示符扩展序列:
print -P '%B'"$1"'%b'
当然,您的$1
字符串本身不能包含其他扩展序列,也不能包含任何用于更改粗体的 SGR 控制序列。这不会给您带来学习tput
以及 terminfo 功能如何工作的挑战。
答案2
%
可以使用参数扩展标志:
echo "${(%):-%B}$1${(%):-%b}"
zsh 有一个print
内置函数,必须-P
执行提示扩展(注意:如果 $1 包含提示序列,它们将被解释为这样):
print -P -- "%B$1%b"
您可能想要打印所有参数,而不仅仅是第一个位置参数(使用$@
/ $*
)。
如果没有给出参数,您可能不想打印任何内容(甚至不打印换行符)(仅在$#
大于零时打印,或使用+
参数扩展并告诉print
输出列)。
您可能想要禁用反斜杠转义符 ( print -r
) 的类似回显的解释。
print_bold() {
local IFS=' '
print -rC1 -- ${1+"${(%):-%B}$*${(%):-%b}"}
}
"$*"
扩展为由第一个字符分隔的位置参数IFS
(默认情况下是空格,但上面已明确设置)。