我正在尝试设置我的PS1
提示变量以动态选择颜色。为此,我使用颜色名称定义了一堆局部变量:
$ echo $Green
\033[0;32m
但我希望在动态分配变量时使用它们,但我无法弄清楚如何正确扩展它们:
> colorstr="\${$color}"
> echo $colorstr
${Green}
我已经尝试了十几种eval
,echo
和双引号的组合,但似乎都没有。扩展变量的逻辑方式(我认为)会导致错误:
> colorstr="${$color}"
-bash: ${$color}: bad substitution
(为清楚起见,我使用>
代替$
作为提示字符,但我使用的是bash)
如何扩展该变量?即以某种方式将“绿色”一词改为值\033[0;32m
?并且优先使用bash或终端解析\033[0;32m
也是绿色。
${!x}
和eval echo $x
,所以我接受了这些作为解决方案。对于(也许是病态的)好奇,函数和PS1
变量都在这个要点上:https://gist.github.com/4383597
答案 0 :(得分:53)
使用eval
是经典解决方案,但bash
有更好的(更容易控制,更少犹豫)解决方案:
${!colour}
Bash(4.1)reference manual说:
如果参数的第一个字符是感叹号(!),则是变量间接的级别 介绍。 Bash使用从参数的其余部分形成的变量的值 变量的名称;然后展开此变量,并在其余部分中使用该值 替换,而不是参数本身的值。这被称为间接 扩展
例如:
$ Green=$'\033[32;m'
$ echo "$Green" | odx
0x0000: 1B 5B 33 32 3B 6D 0A .[32;m.
0x0007:
$ colour=Green
$ echo $colour
Green
$ echo ${!colour} | odx
0x0000: 1B 5B 33 32 3B 6D 0A .[32;m.
0x0007:
$
(odx
命令非常非标准,但只是将数据转换为十六进制格式,右侧显示可打印字符。由于普通echo
没有显示任何内容,我需要看到被回应的东西,我用了一个24年前我写的老朋友。)
答案 1 :(得分:11)
使用eval应该这样做:
green="\033[0;32m"
colorstr="green"
eval echo -e "\$$colorstr" test # -e = enable backslash escapes
test
最后一次测试是绿色。
答案 2 :(得分:1)
Bash支持关联数组。当你可以使用dict时,不要使用间接。如果您没有关联数组,请升级到bash 4,ksh93或zsh。显然mksh最终也会添加它们,所以应该有很多选择。
function colorSet {
typeset -a \
clrs=(black red green orange blue magenta cyan grey darkgrey ltred ltgreen yellow ltblue ltmagenta ltcyan white) \
msc=(sgr0 bold dim smul blink rev invis)
typeset x
while ! ${2:+false}; do
case ${1#--} in
setaf|setab)
for x in "${!clrs[@]}"; do
eval "$2"'[${clrs[x]}]=$(tput "${1#--}" "$x")'
done
;;
misc)
for x in "${msc[@]}"; do
eval "$2"'[$x]=$(tput "$x")'
done
;;
*)
return 1
esac
shift 2
done
}
function main {
typeset -A fgColors bgColors miscEscapes
if colorSet --setaf fgColors --setab bgColors --misc miscEscapes; then
if [[ -n ${1:+${fgColors[$1]:+_}} ]]; then
printf '%s%s%s\n' "${fgColors[${1}]}" "this text is ${1}" "${miscEscapes[sgr0]}"
else
printf '%s, %s\n' "${1:-Empty}" 'no such color.' >&2
return 1
fi
else
echo 'Failed setting color arrays.' >&2
return 1
fi
}
main "$@"
虽然我们正在使用eval
,但由于其他原因,它是一种不同类型的间接。请注意如何保证安全。
答案 3 :(得分:0)
您需要为函数编写别名。查看http://tldp.org/LDP/abs/html/functions.html,体面的小教程和一些示例。
编辑: 对不起,看起来我误解了这个问题。首先,看起来您使用的变量是错误的,请查看http://www.thegeekstuff.com/2010/07/bash-string-manipulation/。还有什么调用这个脚本?您是将此添加到.bash_profile还是这是您的用户可以启动的脚本?使用导出应该使更改立即生效而无需重新编译。
var Green="\[\e[32m\]"
var Red="\[\e41m\]"
export PS1="${Green} welcome ${Red} user>"
答案 4 :(得分:0)
您的第一个结果显示了问题:
$ echo $Green \033[0;32m
变量Green包含一串a backlash, a zero, a 3, etc.
。
由Green="\033[0;32m"
设定。因此,它不是颜色代码
需要解释变量内的文本(使用echo -e,printf或$' ...')。
让我用代码解释一下:
$ Green="\033[0;32m" ; echo " $Green test "
\033[0;32m test
你的意思是:
$ Green="$(echo -e "\033[0;32m" )" ; echo " $Green test "
test
绿色环保。这可以打印颜色,但对PS1无用:
$ Green="\033[0;32m" ; echo -e " $Green test "
test
因为这意味着字符串必须在echo -e
解释之前才能解释。
更简单的方法(在bash中)是:
$ Green=$'\033[0;32m' ; echo " $Green test "
test
请注意` $'...' `
解决了变量Green
的问题后,通过var colorstr的值间接访问它是第二个问题,可以通过以下方法解决:
$ eval echo \$$colorstr testing colors
testing colors
$ echo ${!colorstr} testing colors
testing colors
注意请不要使用未引用的值(正如我在这里所做的那样,因为值在我的控制之下)。学会正确引用,例如:
$ eval echo \"\$$colorstr testing colors\"
有了这个,你可以写一个PS1等同于:
export PS1="${Green} welcome ${Red} user>"
使用:
Green=$'\033[0;32m' Red=$'\033[0;31m'
color1=Green color2=Red
export PS1="${!color1} welcome ${!color2} user>"