我想更改 .bashrc 文件中的 PS1。 我找到了一个使用 printf 和 %q 指令来转义字符的脚本:
#!/bin/bash
STR=$(printf "%q" "PS1=\u@\h:\w\$ ")
sed -i '/PS1/c\'"$STR" ~/.bashrc
问题是我收到此错误:
script.sh: 2: printf: %q: invalid directive
有什么想法吗?也许还有另一种逃避角色的方法?
printf
命令内置于 bash 中。它也是一个外部命令,通常安装在 /usr/bin/printf
中。在大多数 Linux 系统上,/usr/bin/printf
是 GNU coreutils 实现。
旧版本的 GNU coreutils
printf
命令不支持 %q
格式说明符;它是在2016年10月20日发布的8.25版本中引入的。 bash 的内置 printf
命令确实如此,并且只要 bash 具有内置 printf
命令即可。
错误消息意味着您正在使用 bash 以外的其他工具运行
script.sh
。
由于
#!/bin/bash
行似乎是正确的,您可能正在执行以下操作之一:
sh script.sh
. script.sh
source script.sh
相反,直接执行即可(确保具有执行权限后,如果需要,可以使用
chmod +x
):
./script.sh
或者您可以手动编辑您的
.bashrc
文件。如果正确执行该脚本,则会将此行添加到您的 .bashrc
:
PS1=\\u@\\h:\\w\$\
(该行末尾的空格很重要。)或者您可以像这样更简单地做到这一点:
PS1='\u@\h:\w\$ '
脚本的一个问题是它将替换提到 PS1
的
每一行。如果您只设置一次并且不引用它,那很好,但是如果您有类似的内容:
if [ ... ] ; then
PS1=this
else
PS1=that
fi
那么脚本就会彻底搞乱它。就是有点太聪明了。
Keith Thompson 在他的回答中给出了很好的建议。但是 FWIW,您可以通过在命令名称前面加上
builtin
来强制 bash 使用内置命令,例如
builtin printf "%q" "PS1=\u@\h:\w\$ "
相反,
command printf "%s\n" some stuff
强制 bash 使用外部命令(如果它能找到)。
function
时,
command
可用于调用磁盘上的命令。但是,command
不 会调用磁盘上的命令来代替具有相同名称的 Bash 内置命令,它仅用于抑制 shell 函数的调用。 (感谢 Rockallite 提醒我注意这个错误)。
可以启用或禁用特定的 bash 内置函数(也许您的 .bashrc 正在对 printf 执行此操作)。详情请参阅
help enable
。我想我应该提到你可以使用
type printf
找出当你给它一个裸
printf
时bash将运行什么样的实体(shell函数、内置或外部命令)。您可以通过传递 type
-a
选项来获取具有给定名称的所有命令的列表,例如
type -a printf
您可以使用 grep 查看 .bashrc 文件中包含 PS1 的行:
grep 'PS1' ~/.bashrc
或
grep -n0 --color=auto 'PS1=' ~/.bashrc
它为您提供行号和精美的彩色输出。然后你可以使用行号来强制 sed 只修改你想要更改的行。
例如,如果 grep 告诉您要更改的行是第 7 行,您可以这样做
sed -i '7c\'"$STR" ~/.bashrc
编辑它。或者更好,
sed -i~ '7c\'"$STR" ~/.bashrc
它会备份文件的原始版本,以防您犯错误。
使用
sed -i
时,我通常会先在没有 -i
的情况下进行测试运行,以便输出到达 shell,让我在将修改写入文件之前查看修改的作用。
对于使用
fish-shell
的其他人,我没有意识到 fish-shell
实际上有自己的“内置”printf
函数,但不支持 %q
指令。当我尝试在 fish
shell 中使用该指令时,我会收到如下错误消息:
%q: invalid conversion specification
当我退出
fish-shell
并直接使用zsh
时,我能够毫无问题地使用printf '%q\n' ...
。