Erstellen einer Funktion, die den Namen und den Wert einer Variablen anzeigt

7

Ich möchte eine Funktion schreiben (nennen wir sie superEcho), die einen Variablennamen als Eingabe verwendet. Die Funktion sollte den Namen und den Wert dieser Variablen drucken

function superEcho
{
     echo "$1: ?????"
}

var=100

superEcho var

Ich möchte, dass dieses Skript zurückkehrt

var: 100

Aber ich weiß nicht, was ich anstelle von "?????" in der superEcho Funktion.

Biedrona
quelle

Antworten:

7

POSIXly:

superEcho() {
  eval 'printf "%s\n" "$1: ${'"$1"'}"'
}

Wie bei der bash-spezifischen ${!var}wurde diese Erwartung $1bereinigt und enthält einen gültigen Variablennamen. Andernfalls handelt es sich um eine Sicherheitsanfälligkeit bezüglich willkürlicher Befehlsinjektion.

Sie können die Desinfektion in der Funktion durchführen:

superEcho() {
  case $1 in
    ("" | *[!_0-9abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ]* | [0-9]*)
      printf >&2 'Invalid variable name: "%s"\n' "$1"
      return 1;;
    (*) eval 'printf "%s\n" "$1: ${'"$1"'}"'
  esac
}

Beachten Sie, dass für Variablen vom Typ Array oder assoziatives Array in bashoder ksh(POSIX shhat kein Array, außer "$@"das Sie hier nicht verwenden könnten, da dies die Argumente der superEchoFunktion selbst wären ) nur der Wert des Indexelements ausgegeben wird 0, während in zshDies würde die Verkettung der Werte mit dem ersten Zeichen von $IFS(und mit SPC-Zeichen in yash) ausgeben .

In ksh, zsh, bashoder yash(die 4 Bourne artige Schalen mit Array - Unterstützung). Siehe auch typeset -p varDrucken der Definition und der Attribute einer Variablen.

Stéphane Chazelas
quelle
Gibt es einen bestimmten Grund, warum Sie die 26 mal 2 Alphabete auflisten müssen? Wenn der Bereich 0-9 verstanden wird, warum dann nicht az?
@Rakesh [a-z]ist vom Gebietsschema abhängig und enthält im Allgemeinen viel mehr als diese 26 Zeichen (und die POSIX-Spezifikation und die meisten (wenn auch nicht alle) Shells haben diese nicht in Variablennamen). Alternative wäre, eine Subshell zu starten und darin zu haben export LC_ALL=C.
Stéphane Chazelas
@Rakesh, POSIX garantiert nicht, dass 0-9nur 0123456789beide übereinstimmen (außer natürlich im Gebietsschema C/ POSIX), aber in der Praxis ist dies der Fall. Ich würde ein Gebietsschema als kaputt betrachten, in dem dies nicht der Fall ist.
Stéphane Chazelas
2

Verwendung ${!variablename}:

function superEcho
{
    printf '%s: %s\n' "$1" "${!1}"
}
Kusalananda
quelle
Bitte ignorieren Sie meinen vorherigen (jetzt gelöschten) Kommentar, wenn Sie ihn zufällig gesehen haben. Ich war dumm.
Terdon
0

Ich mache es anders herum. Ich möchte häufig den Variablennamen für E-Mails, Protokolle oder Flags (auf die Festplatte geschrieben) verwenden, damit alles, was zu einem Gerät gehört, auf dieselbe Weise benannt wird - unter Verwendung des Variablennamens als Basis.

RPiZero=10

ReadRPiTemp ()
{
    eval ReadSegment='$'$1
    echo "variable content: $ReadSegment"
    echo "variable name: $1"
}

ReadRPiTemp RPiZero
# NOT ReadRPiTemp "$RPiZero"

Oben wird in sh und bash funktionieren. Da ich in meiner Arbeit mit sh kompatibel sein muss, habe ich es versäumt, einen geeigneten Weg zu erwähnen, um dasselbe in Bash zu tun.

RPiZero=10

ReadRPiTemp ()
{
    declare -n ReadSegment=$1
    echo "variable content: $ReadSegment"
    echo "variable name: $1"
}

ReadRPiTemp RPiZero
# NOT ReadRPiTemp "$RPiZero"

Beide oben genannten werden gleich gedruckt:

variable content: 10
variable name: RPiZero
Pila
quelle