Bash genera errore, riga 8: $ 1: variabile non associata


15

Sto cercando di imparare come usare getopts in modo da poter avere script con input analizzato (anche se penso che getopts potrebbe essere migliore). Sto provando a scrivere un semplice script per restituire le percentuali di utilizzo delle partizioni. Il problema è che una delle mie funzioni bash non sembra che mi riferisca $1come variabile all'interno della funzione. Il motivo per cui faccio riferimento $1è perché alla get_percentfunzione può essere passato un punto di montaggio come argomento facoltativo da visualizzare anziché tutti i punti di montaggio.

Il copione

#!/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
# ...

Il risultato

$ 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

Non penso che abbia a che fare con questo getopts, vero? Lo script viene chiuso -uprima di chiamare getopts.
ilkkachu,

@ikkachu no, credo di no. Ma non sono sicuro di poter cambiare il titolo ora.
Timothy Pulliam,

Dovrebbe esserci quel piccolo testo "modifica" sotto il post, proprio sotto i tag in una domanda
ilkkachu

Risposte:


29

set -usi interromperà esattamente come descritto se si fa riferimento a una variabile che non è stata impostata. Stai invocando il tuo script senza argomenti, quindi get_percentviene invocato senza argomenti, causando il $1disinserimento.

O verificalo prima di invocare la tua funzione o usa espansioni predefinite ( ${1-default}si espanderà a defaultse non già impostato su qualcos'altro).


Lo sospettavo, ma non riuscivo a pensare a un modo per aggirarlo. L'espansione predefinita sembra averlo corretto. Grazie mille!
Timothy Pulliam,

7
In particolare, si potrebbe usare [ -n "${1-}" ](cioè con un valore predefinito vuoto) per vedere se il parametro è impostato e non vuoto; o [ "${1+x}" = x ]per vedere se è impostato, anche se vuoto.
ilkkachu,

Ottengo ancora un errore variabile non if [[ -n ${1-default} ]]
associato

6

Questo è l'effetto di set -u.

È possibile verificare $#all'interno della funzione ed evitare riferimenti $1se non è impostato.

Con $#te puoi accedere al numero di parametri. Nel contesto globale è il numero di parametri per lo script, in una funzione è il numero di parametri per la funzione.

Nel contesto della domanda, lo è

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

Si noti che è necessario utilizzare [ $# -ge 1 ] && [ -n "$1" ]e non [ $# -ge 1 -a -n "$1" ], perché questo prima valutare $1e quindi verificare $#.


Puoi spiegare di più come usare $ # e come controllarlo? Grazie
Chaitanya Bapat il

1
Ho aggiunto un esempio.
RalfFriedl,

3

Dato che questo è bashpossibile, è possibile eludere il controllo per $1essere impostato e solo usare "$@"( $1è il primo parametro, $@sono tutti loro; quando è racchiuso tra virgolette, scompare completamente se non ha valori, il che evita che venga catturato set -u):

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

Ho anche modificato leggermente il resto della riga in modo da non ottenere {spazio} {tab} {spazio} tra i due valori che hai emesso, ma ti ho detto che ottieni solo un {tab}. Se vuoi davvero i due spazi invisibili, modifica il awkda usare printf "%s \t %s\n", $1, $5.


Dovrò esaminare questo. Non ho familiarità con quel tipo di variabile. Grazie
Timothy Pulliam,

@TimothyPulliam Ho aggiunto una breve spiegazione $@per te
roaima
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.