2016-03-25 12 views
1

Ich arbeite derzeit an der Bereinigung einiger Shell-Skripte. Während das zu tun, stieß ich auf etwas, das wie folgt aussieht:Understanding Indirection

if [ ${#VARA} -eq 0 ] || [ ${#$VARB} -eq 0 ] || [ ${$VARC} -eq 0 ]; then 
    ... 
fi 

Wie Sie sehen können, gibt mit Variablen hier drei verschiedene Arten von Dingen los sind: ${#V}, ${#$V} und ${$V}. Ich würde gerne eine Erklärung von jedem von diesen bitte lieben. (Plus Shellcheck is complaining über die letzte.)

+1

Mein Bash beschwert sich schon über die zweite. Welche Schale ist es? Irgendeine Chance, dass der ursprüngliche Autor nicht wusste, was er tat und gerade alle drei versuchte. Die erste ist die String-Länge des VARAs-Wertes. – Harald

+0

@ Harald gibt es eine sehr gute Chance dafür. Und ja, es ist Bash. Die fragliche Zeile ist in einem sehr großen Skript. Ich kann nicht versprechen, dass es überhaupt verwendet wird, aber ich fand es einfach interessant, da ich die Syntax vorher noch nie gesehen hatte. –

+0

Kein Wunder, dass du es nicht gesehen hast, wenn es nicht funktioniert (außer dem 1.) :-) Oder vielleicht hat es in alten Versionen von bash funktioniert. – Harald

Antwort

1

Diese Syntax ist Teil der POSIX (Thence Bash) Shell-Parameter-Erweiterung. Es zählt Anzahl der Zeichen für eine Variable:

$ myvar="foo" && echo ${#myvar} 
3 

Die letzten zwei Einsen ${#$VARB} und ${$VARC} keine gültige Syntax haben. Sie können eine Variable nicht auf diese Weise deklarieren.

Ganz ähnlich wie Ihre ${$VARC} ist der gültige \$$myvar, verwendet für indirect reference mit eval oder echo. Diese Syntax bezieht sich auf den Literal-String "$foo" (wenn myvar="foo"). Wie @chepner erwähnt, because of eval, wird es nicht empfohlen, es zu verwenden. Die Bash 2.0 führte die ${!myvar} Syntax für indirekte Variablenreferenz ein, die eine viel vorzuziehende Alternative ist.

Hinweis: Sie sollten Großbuchstaben für Variablennamen vermeiden, die nicht mit Shell-Variablen verwechselt werden, die nach Konvention ebenfalls überladen sind.

+1

'$ {# myvar}' ist nicht nur 'bash', sondern Teil der POSIX-Shell-Spezifikation. – chepner

+1

'othervar = \ $$ VARC' setzt' othervar' auf die Literal-Zeichenkette '$ foo' (wenn' foo' die Erweiterung von '$ VARC' ist). – chepner

+0

Danke @chepner. Aktualisierte meine ungefähre Formulierung. – SLePort