Bash löst Fehler aus, Zeile 8: $ 1: ungebundene Variable

12

Ich versuche zu lernen, wie man getopts verwendet, damit ich Skripte mit analysierter Eingabe haben kann (obwohl ich denke, dass getopts besser sein könnte). Ich versuche nur ein einfaches Skript zu schreiben, um die Prozentsätze der Partitionsnutzung zurückzugeben. Das Problem ist, dass eine meiner Bash-Funktionen nicht zu mögen scheint, dass ich $1als Variable innerhalb der Funktion verweise . Der Grund, auf den ich verweise, $1ist, dass der get_percentFunktion ein Einhängepunkt als optionales Argument übergeben werden kann, das anstelle aller Einhängepunkte angezeigt werden soll.

Das Skript

#!/usr/bin/bash

set -e
set -u
set -o pipefail

get_percent(){
    if [ -n "$1" ] 
    then
        df -h $1 | tail -n +2 | awk '{ print $1,"\t",$5 }'
    else
        df -h | tail -n +2 | awk '{ print $1,"\t",$5 }'
    fi
}

usage(){
    echo "script usage: $(basename $0) [-h] [-p] [-m mount_point]" >&2
}

# If the user doesn't supply any arguments, we run the script as normal
if [ $# -eq 0 ];
then
    get_percent
    exit 0
fi
# ...

Die Ausgabe

$ bash thing.sh
thing.sh: line 8: $1: unbound variable

$ bash -x thing.sh
+ set -e
+ set -u
+ set -o pipefail
+ '[' 0 -eq 0 ']'
+ get_percent
thing.sh: line 8: $1: unbound variable
Timothy Pulliam
quelle
Ich glaube nicht, dass das etwas damit zu tun getoptshat, oder? Ihr Skript wird -uvor dem Aufruf beendet getopts.
Ilkkachu
@ikkachu nein ich denke es nicht. Aber ich bin mir nicht sicher, ob ich den Titel jetzt ändern kann.
Timothy Pulliam
Es sollte diesen kleinen "bearbeiten" Text unter dem Beitrag geben, direkt unter den Tags in einer Frage
ilkkachu

Antworten:

29

set -uwird genau so abgebrochen, wie Sie es beschreiben, wenn Sie auf eine Variable verweisen, die nicht festgelegt wurde. Sie rufen Ihr Skript ohne Argumente auf, werden also get_percentohne Argumente aufgerufen, was $1dazu führt , dass es nicht gesetzt wird.

Überprüfen Sie dies entweder, bevor Sie Ihre Funktion aufrufen, oder verwenden Sie Standarderweiterungen ( ${1-default}wird erweitert, defaultwenn nicht bereits etwas anderes festgelegt ist).

DopeGhoti
quelle
Ich vermutete das, aber ich konnte mir keinen Weg vorstellen, es zu umgehen. Die Standarderweiterung scheint das Problem behoben zu haben. Vielen Dank!
Timothy Pulliam
6
Insbesondere könnte man verwenden [ -n "${1-}" ](dh mit einem leeren Standardwert), um zu sehen, ob der Parameter gesetzt und nicht leer ist; oder um [ "${1+x}" = x ]zu sehen, ob es gesetzt ist, auch wenn es leer ist.
Ilkkachu
Ich bekomme immer noch ungebundenen Variablenfehler trotz der Verwendung vonif [[ -n ${1-default} ]]
Chaitanya Bapat
6

Dies ist die Wirkung von set -u.

Sie können $#die Funktion überprüfen und Verweise vermeiden, $1wenn sie nicht festgelegt ist.

Mit können $#Sie auf die Anzahl der Parameter zugreifen. Im globalen Kontext ist es die Anzahl der Parameter für das Skript, in einer Funktion die Anzahl der Parameter für die Funktion.

Im Kontext der Frage ist es

if [ $# -ge 1 ] && [ -n "$1" ]
then
    df -h $1 | tail -n +2 | awk '{ print $1,"\t",$5 }'
else
    df -h | tail -n +2 | awk '{ print $1,"\t",$5 }'
fi

Beachten Sie, dass Sie verwenden müssen [ $# -ge 1 ] && [ -n "$1" ]und nicht [ $# -ge 1 -a -n "$1" ], da dies zuerst ausgewertet $1und dann überprüft werden würde $#.

RalfFriedl
quelle
Können Sie mehr erklären, wie man $ # verwendet und wie man es überprüft? Vielen Dank
Chaitanya Bapat
1
Ich habe ein Beispiel hinzugefügt.
RalfFriedl
2

Da dies der bashFall ist , können Sie die Prüfung für $1das Setzen umgehen und nur verwenden "$@"( $1ist der erste Parameter, $@sind alle von ihnen; wenn es in doppelten Anführungszeichen steht, verschwindet es vollständig, wenn es keine Werte hat, wodurch verhindert wird, dass es abgefangen wird set -u):

get_percent() {
    df -h "$@" | awk 'NR>1 { printf "%s\t%s\n", $1, $5 }'
}

Ich habe auch den Rest der Zeile leicht angepasst, damit zwischen den beiden von Ihnen ausgegebenen Werten kein {Leerzeichen} {Tab} {Leerzeichen} angezeigt wird, sondern nur ein {Tab}. Wenn Sie die beiden unsichtbaren Leerzeichen wirklich möchten, ändern Sie die awkzu verwendende printf "%s \t %s\n", $1, $5.

Roaima
quelle
Ich werde das untersuchen müssen. Ich bin mit diesem Variablentyp nicht vertraut. Vielen Dank
Timothy Pulliam
@ TimothyPulliam Ich habe eine kurze Erklärung $@für Sie hinzugefügt
Roaima