Bash espande la variabile in una variabile

Sto cercando di impostare la mia variabile prompt PS1 per scegliere dynamicmente un colore. Per fare questo, ho definito un gruppo di variabili locali con i nomi dei colors:

 $ echo $Green \033[0;32m 

ma speravo di usarli nell’assegnazione dynamic di variabili, ma non riesco a capire come espanderli correttamente:

 > colorstr="\${$color}" > echo $colorstr ${Green} 

Ho provato una dozzina di combinazioni di eval , echo e virgolette e nessuno sembra funzionare. Il modo logico (ho pensato) per espandere la variabile risulta in un errore:

 > colorstr="${$color}" -bash: ${$color}: bad substitution 

(per chiarezza ho usato > invece di $ per il carattere prompt, ma sto usando bash)

Come posso espandere quella variabile? cioè, in qualche modo ottenere la parola “Verde” per il valore \033[0;32m ? E preferibilmente, bash o l’analisi del terminale che \033[0;32m come il colore verde troppo.

EDIT: stavo usando male ${!x} e eval echo $x precedenza, quindi ho accettato quelli come soluzioni. Per il (forse morbosamente) curioso, le funzioni e la variabile PS1 sono in questo gist: https://gist.github.com/4383597

L’utilizzo di eval è la soluzione classica, ma bash ha una soluzione migliore (più facilmente controllabile, meno blunderbuss):

  • ${!colour}

Il manuale di riferimento di Bash (4.1) dice:

Se il primo carattere del parametro è un punto esclamativo (!), Viene introdotto un livello di indiretta variabile. Bash utilizza il valore della variabile formata dal resto del parametro come nome della variabile; questa variabile viene quindi espansa e tale valore viene utilizzato nel resto della sostituzione, anziché il valore del parametro stesso. Questo è noto come espansione indiretta .

Per esempio:

 $ 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: $ 

(Il comando odx è molto non standard, ma semplicemente scarica i dati in un formato esadecimale con caratteri stampabili mostrati sulla destra. Poiché l’ echo semplice non mostrava nulla e avevo bisogno di vedere ciò che veniva echeggiato, usai un vecchio amico Ho scritto circa 24 anni fa.)

L’uso di eval dovrebbe farlo:

 green="\033[0;32m" colorstr="green" eval echo -e "\$$colorstr" test # -e = enable backslash escapes test 

L’ultimo test è a colors verde.

Bash supporta gli array associativi. Non usare l’indirezione quando potresti usare un dict. Se non si dispone di array associativi, eseguire l’aggiornamento a bash 4, ksh93 o zsh. Apparentemente mksh li sta aggiungendo alla fine, quindi dovrebbe esserci molta scelta.

 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 "[email protected]" 

Anche se stiamo usando eval , è un tipo diverso di indiretta per un motivo diverso. Nota come sono fatte tutte le garanzie necessarie per rendere questo sicuro.

Vedi anche: http://mywiki.wooledge.org/BashFAQ/006

Dovrai scrivere un alias su una funzione. Dai un’occhiata a http://tldp.org/LDP/abs/html/functions.html , un piccolo tutorial decente e alcuni esempi.

EDIT: Mi dispiace, sembra che ho frainteso il problema. Per prima cosa sembra che tu stia usando le variabili errate, controlla http://www.thegeekstuff.com/2010/07/bash-string-manipulation/ . Inoltre, che cosa sta invocando questo script? Stai aggiungendo questo a .bash_profile o è uno script che possono essere lanciati dagli utenti? L’utilizzo dell’esportazione dovrebbe rendere effettive le modifiche immediatamente senza il necessario relog.

 var Green="\[\e[32m\]" var Red="\[\e41m\]" export PS1="${Green} welcome ${Red} user>" 

Il tuo primo risultato mostra il problema:

 $ echo $Green \033[0;32m 

La variabile Green contiene una stringa di a backlash, a zero, a 3, etc. .

È stato impostato da: Green="\033[0;32m" . Come tale non è un codice colore.
Il testo all’interno della variabile deve essere interpretato (usando echo -e, printf o $ ‘…’).

Lasciami spiegare con il codice:

 $ Green="\033[0;32m" ; echo " $Green test " \033[0;32m test 

Quello che intendi fare è:

 $ Green="$(echo -e "\033[0;32m" )" ; echo " $Green test " test 

In ottimo colore verde. Questo potrebbe stampare il colore ma non sarà utile per PS1:

 $ Green="\033[0;32m" ; echo -e " $Green test " test 

Ciò significa che la stringa deve essere interpretata da echo -e prima che funzioni.

Un modo più semplice (in bash) è:

 $ Green=$'\033[0;32m' ; echo " $Green test " test 

Si prega di notare il ` $'...' `

Avendo risolto il problema della variabile Green , accedendovi indirettamente dal valore di var colorstr è un secondo problema che potrebbe essere risolto da entrambi:

 $ eval echo \$$colorstr testing colors testing colors $ echo ${!colorstr} testing colors testing colors 

Nota Si prega di non lavorare con valori non quotati (come ho fatto qui perché i valori erano sotto il mio controllo) in generale. Impara a citare correttamente, come:

 $ eval echo \"\$$colorstr testing colors\" 

E con questo, potresti scrivere 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>"