Estoy intentando configurar mi variable de solicitud de PS1
para elegir dinámicamente un color. Para hacer esto, he definido un grupo de variables locales con nombres de colores:
$ echo $Green \033[0;32m
pero esperaba usarlos en la asignación dinámica de variables, pero no puedo encontrar la manera de expandirlos correctamente:
> colorstr="\${$color}" > echo $colorstr ${Green}
Probé una docena de combinaciones de eval
, echo
y comillas dobles, y ninguna parece funcionar. La forma lógica (pensé) de expandir los resultados de la variable en un error:
> colorstr="${$color}" -bash: ${$color}: bad substitution
(para mayor claridad, he usado >
lugar de $
para el carácter de solicitud, pero estoy usando bash)
¿Cómo puedo expandir esa variable? es decir, de alguna manera obtener la palabra “Verde” en el valor \033[0;32m
? Y, preferiblemente, tenga bash o el análisis de terminal que \033[0;32m
como el color verde también.
EDITAR: Estaba mal-usando ${!x}
y eval echo $x
previamente, así que los he aceptado como soluciones. Para el (quizás morbosamente) curioso, las funciones y la variable PS1
están en esta esencia: https://gist.github.com/4383597
El uso de eval
es la solución clásica, pero bash
tiene una mejor solución (más fácil de controlar, menos similar al blunderbuss):
${!colour}
El manual de referencia de Bash (4.1) dice:
Si el primer carácter de parámetro es un signo de exclamación (!), Se introduce un nivel de indirección variable. Bash usa el valor de la variable formada a partir del rest del parámetro como el nombre de la variable; esta variable luego se expande y ese valor se usa en el rest de la sustitución, en lugar del valor del parámetro en sí mismo. Esto se conoce como expansión indirecta .
Por ejemplo:
$ 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: $
(El comando odx
es muy no estándar, pero simplemente vuelca sus datos en un formato hexadecimal con caracteres imprimibles que se muestran a la derecha. Como el echo
no mostró nada y necesitaba ver lo que se repetía, utilicé un viejo amigo Escribí hace unos 24 años.)
Usar eval debería hacerlo:
green="\033[0;32m" colorstr="green" eval echo -e "\$$colorstr" test # -e = enable backslash escapes test
La última prueba es de color verde.
Bash admite matrices asociativas. No use la indirección cuando podría usar un dict. Si no tiene matrices asociativas, actualice a bash 4, ksh93 o zsh. Aparentemente, mksh también los está agregando, así que debería haber muchas opciones.
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 "$@"
Aunque estamos usando eval
, es un tipo diferente de indirección por una razón diferente. Tenga en cuenta cómo se hacen todas las garantías necesarias para hacer que esto sea seguro.
Ver también: http://mywiki.wooledge.org/BashFAQ/006
Querrá escribir un alias para una función. Consulte http://tldp.org/LDP/abs/html/functions.html , pequeño tutorial decente y algunos ejemplos.
EDITAR: Lo siento, parece que he entendido mal el problema. Primero parece que estás usando las variables incorrectamente, revisa http://www.thegeekstuff.com/2010/07/bash-string-manipulation/ . Además, ¿qué está invocando este script? ¿Está agregando esto al .bash_profile o es este un script que sus usuarios pueden iniciar? El uso de la exportación debe hacer que los cambios entren en vigencia de inmediato sin necesidad de relog.
var Green="\[\e[32m\]" var Red="\[\e41m\]" export PS1="${Green} welcome ${Red} user>"
Su primer resultado muestra el problema:
$ echo $Green \033[0;32m
La variable Verde contiene una cadena de a backlash, a zero, a 3, etc.
Fue establecido por: Green="\033[0;32m"
. Como tal, no es un código de color.
El texto dentro de la variable necesita ser interpretado (usando echo -e, printf o $ ‘…’).
Déjame explicarte con el código:
$ Green="\033[0;32m" ; echo " $Green test " \033[0;32m test
Lo que quieres hacer es:
$ Green="$(echo -e "\033[0;32m" )" ; echo " $Green test " test
En gran color verde. Esto podría imprimir el color, pero no será útil para PS1:
$ Green="\033[0;32m" ; echo -e " $Green test " test
Como significa que la cuerda debe ser interpretada por echo -e
antes de que funcione.
Una manera más fácil (en bash) es:
$ Green=$'\033[0;32m' ; echo " $Green test " test
Tenga en cuenta que ` $'...' `
Habiendo resuelto el problema de la variable Green
, accediendo indirectamente por el valor de var colorstr es un segundo problema que podría ser resuelto por:
$ eval echo \$$colorstr testing colors testing colors $ echo ${!colorstr} testing colors testing colors
Nota: Por favor, no trabaje con valores no citados (como lo hice aquí porque los valores estaban bajo mi control) en general. Aprende a citar correctamente, como:
$ eval echo \"\$$colorstr testing colors\"
Y con eso, podrías escribir una PS1 equivalente a:
export PS1="${Green} welcome ${Red} user>"
con:
Green=$'\033[0;32m' Red=$'\033[0;31m' color1=Green color2=Red export PS1="${!color1} welcome ${!color2} user>"