2009-11-07 5 views
10

Diciamo che ho il nome di una variabile memorizzata in un'altra variabile:variabili di shell di ricerca per nome, indirettamente

myvar=123 
varname=myvar 

ora, mi piacerebbe ottenere 123 da solo utilizzando variabile $ varname. C'è un modo diretto per quello? Ho trovato tale bash incorporato per la ricerca per nome, così si avvicinò con questo:

function var { v="\$$1"; eval "echo "$v; } 

così

var $varname # gives 123 

Il che non sembra troppo male alla fine, ma mi chiedo se io perso qualcosa di più ovvio. Grazie in anticipo!

+0

Questo è contrassegnato come un duplicato di una domanda che è stata posta 6 anni dopo? Anche IMHO questa domanda + risposte è più chiara di quelle collegate. – inger

risposta

12

Dal man page of bash:

${!varname} 

Se il primo carattere di parametro è un punto esclamativo, si introduce un livello di indiretto 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 di la sostituzione, anziché il valore del parametro stesso. Questo è noto come espansione indiretta.

+0

Certo, è tutto. Provato per RTFM, ma in qualche modo questa descrizione: ----------------- $ {! Prefix *} $ {! Prefix @} Prefisso corrispondente ai nomi. Si espande ai nomi delle variabili i cui nomi iniziano con il prefisso, separati dal primo carattere della variabile speciale IFS . Quando viene utilizzato @ e l'espansione appare tra virgolette doppie, ciascun nome di variabile si espande in una parola separata. ----------------- non mi ha colpito come risposta ovvia. Cheers! – inger

+0

@DigitalRoss: La domanda è stata contrassegnata con "bash", quindi perché vuoi limitare la risposta allo standard posix? – tangens

+1

È una risposta soddisfacente e sì si applica a bash. Immagino che la risposta perfetta annuncerà '$ {! Varname}' e quindi noteremo il problema della portabilità per evitare che l'OP abbia dei problemi. – DigitalRoss

12

Non esiste una sintassi diretta conforme a Posix, solo un ism bash. Io di solito faccio questo:

eval t="\$$varname" 

Ciò funzionerà su qualsiasi shell POSIX, compresi gli impianti in cui bash è la shell di login e /bin/sh è qualcosa di più piccolo e più veloce come ash. Mi piace bash e lo uso per la mia shell di login ma evito i bashismi nei file di comando.


Nota: un problema con la scrittura di script specifici di bash è che anche se è possibile contare sul fatto che bash sia installato, potrebbe trovarsi in qualsiasi punto del percorso. Potrebbe essere una buona idea in questo caso di utilizzare il completamente generale /usr/bin/envshebang stile, ma si noti che questo è ancora portatile non al 100% e problemi di sicurezza.

+0

A seconda del contesto in cui è necessario il valore, è possibile utilizzare '$ (eval \ $$ varname)' piuttosto che un compito. –

+0

Ho provato quasi quello, ma l'ho perso. Più breve di matto per questo! – inger

+0

non è '$ (....)' non-posix? Non dovrebbe invece essere \ "eval \ $$ varname' \'? –

1

${!varname} dovrebbe fare il trucco

$ var="content" 
$ myvar=var 
$ echo ${!myvar} 
content 
+0

Grazie, sembra che la tua risposta sia arrivata un attimo dopo che tangens, quindi ho selezionato quello :) – inger

1

io di solito guardo Advance Bash-Scripting Guide quando ho bisogno di rinfrescare le mie capacità Bash.

Per quanto riguarda il tuo look interrogazioni Indirect References

notazione è:

Version < 2 
\$$var 

Version >= 2 
${!varname} 
+0

Hmm, ho guardato velocemente quella guida - apparentemente troppo velocemente :) Sembra come se dovessi leggerlo correttamente .. grazie per il suggerimento ! – inger

+0

È il mio rapido riferimento di scelta, tendo ad usarlo più frequentemente rispetto alle pagine man. Ma come dici tu, una rapida occhiata a volte non è abbastanza. –

+0

In generale, l'ABS dovrebbe essere preso con un enorme granello di sale. Niente di male in questa risposta di per sé, però. – tripleee

0
# bmuSetIndirectVar() 
# TO DOUBLE CHECK THIS COMMENT AND DEMO 
# This function is an helper to read indirect variables. 
# i.e. get the content of a variable whose name is saved 
# within an other variable. Like: 
# MYDIR="/tmp" 
# WHICHDIR="MYDIR" 
#  bmuSetIndirectVar "WHICHDIR" "$MYDIR" 
# 
bmuSetIndirectVar(){ 
    tmpVarName=$1 
    locVarName=$1 
    extVarName=$2 
    #echo "debug Ind Input >$1< >$2<" 
    eval tmpVarName=\$$extVarName 
    #echo "debug Ind Output >$tmpVarName< >$extVarName<" 
    export $locVarName="${tmpVarName}" 
} 

Attualmente sto usando questa piccola funzione. Non ne sono completamente soddisfatto e ho visto diverse soluzioni sul web (se potessi ricordare le scriverei qui), ma sembra funzionare. All'interno di queste poche righe c'è già una certa ridondanza e dati extra ma è stato utile per il debug.

Se volete vedere al suo posto, cioè dove Io lo utilizzo, verificare: https://github.com/mariotti/bmu/blob/master/bin/backmeup.shellfunctions.sh

Naturalmente non è la soluzione migliore, ma mi ha fatto andare avanti con il lavoro, in la speranza Posso sostituirlo con qualcosa di un po 'più generico presto.

+0

Prima delle domande;) Ciò che non mi piace di questa funzione è che utilizzo un "eval" che in genere è un trigger per un cattivo design. Ovviamente ci sono posti dove ne hai bisogno. Quello che mi piace è che usando una funzione posso staccare il codice dal problema e ottimizzarlo in seguito. Forse anche introdurre un controllo di versione della shell o simili. – mariotti

Problemi correlati