Bash melempar kesalahan, baris 8: $ 1: variabel tidak terikat

15

Saya mencoba mempelajari cara menggunakan getopts sehingga saya dapat memiliki skrip dengan input yang diuraikan (walaupun saya pikir getopts bisa lebih baik). Saya mencoba menulis skrip sederhana untuk mengembalikan persentase penggunaan partisi. Masalahnya adalah bahwa salah satu fungsi bash saya sepertinya tidak seperti yang saya referensi $1sebagai variabel di dalam fungsi. Alasan saya referensi $1adalah karena get_percentfungsi dapat melewati titik mount sebagai argumen opsional untuk ditampilkan, bukan semua titik mount.

Naskah

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

Hasil

$ 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
sumber
Saya rasa ini tidak ada hubungannya getopts, bukan? Script Anda keluar karena -usebelum menelepon getopts.
ilkkachu
@ikkachu tidak, kurasa tidak. Tapi saya tidak yakin bisa mengubah judulnya sekarang.
Timothy Pulliam
Seharusnya ada teks "edit" kecil di bawah kiriman, tepat di bawah tag dalam sebuah pertanyaan
ilkkachu

Jawaban:

29

set -uakan dibatalkan persis seperti yang Anda jelaskan jika Anda mereferensikan variabel yang belum ditetapkan. Anda memanggil skrip Anda tanpa argumen, jadi get_percentdipanggil tanpa argumen, menyebabkan $1tidak disetel.

Periksa apakah ini sebelum memanggil fungsi Anda, atau gunakan ekspansi default ( ${1-default}akan meluas ke defaultjika belum diatur ke yang lain).

DopeGhoti
sumber
Saya mencurigai ini, tetapi saya tidak bisa memikirkan jalan lain. Ekspansi default tampaknya telah memperbaikinya. Terima kasih banyak!
Timothy Pulliam
7
Secara khusus, seseorang dapat menggunakan [ -n "${1-}" ](yaitu, dengan nilai default kosong) untuk melihat apakah parameter ditetapkan dan tidak kosong; atau [ "${1+x}" = x ]untuk melihat apakah sudah disetel, meskipun kosong.
ilkkachu
Saya masih mendapatkan error variabel yang tidak terikat meskipun menggunakanif [[ -n ${1-default} ]]
Chaitanya Bapat
6

Ini adalah efek dari set -u.

Anda dapat memeriksa $#di dalam fungsi dan menghindari referensi $1jika tidak disetel.

Dengan $#Anda dapat mengakses sejumlah parameter. Dalam konteks global ini adalah jumlah parameter untuk skrip, dalam suatu fungsi itu adalah jumlah parameter untuk fungsi.

Dalam konteks pertanyaan, itu

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

Perhatikan bahwa Anda harus menggunakan [ $# -ge 1 ] && [ -n "$1" ]dan tidak [ $# -ge 1 -a -n "$1" ], karena yang pertama akan mengevaluasi $1dan kemudian memeriksa $#.

RalfFriedl
sumber
Bisakah Anda menjelaskan lebih lanjut cara menggunakan $ # dan cara memeriksanya? Terima kasih
Chaitanya Bapat
1
Saya menambahkan contoh.
RalfFriedl
3

Karena ini adalah bashAnda dapat menghindari pemeriksaan untuk $1ditetapkan dan hanya menggunakan "$@"( $1adalah parameter pertama, $@semuanya; ketika dikutip ganda, akan hilang sama sekali jika tidak memiliki nilai, yang menghindarkannya ditangkap oleh set -u):

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

Saya juga telah mengubah sedikit sisa baris sehingga Anda tidak mendapatkan {spasi} {tab} {spasi} antara dua nilai yang Anda hasilkan tetapi insead Anda hanya mendapatkan {tab}. Jika Anda benar-benar ingin dua ruang tak terlihat maka ubah awkuntuk menggunakan printf "%s \t %s\n", $1, $5.

roaima
sumber
Saya harus melihat ini. Saya tidak terbiasa dengan tipe variabel itu. Terima kasih
Timothy Pulliam
@TimothyPulliam Saya telah menambahkan penjelasan singkat $@untuk Anda
roaima