Bashでエラーが発生します。行8:$ 1:バインドされていない変数

Bashでエラーが発生します。行8:$ 1:バインドされていない変数

私は構文解析された入力を持つスクリプトを持つことができるようにgetoptsを使用する方法を学びようとしています(getoptsが良いかもしれないと思いますが)。パーティション使用率を返す簡単なスクリプトを作成しようとしています。問題は、私のbash関数の1つが$1関数内で変数として参照する関数が好きではないようです。私が引用した理由は、関数にすべてのマウントポイントを表示するのではなく、表示するオプションの引数でマウントポイントを渡すことができるから$1です。get_percent

スクリプト

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

出力

$ 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

答え1

set -uまだ設定されていない変数を参照すると、説明したように正しく中断されます。引数なしでスクリプトを呼び出すため、引数なしで呼び出されるため、get_percent設定はオフに$1なります。

関数を呼び出す前にこれを確認するか、デフォルトの拡張機能を使用してください(${1:-default}まだ別のものに設定されていない場合は別のものに拡張されます)。default

答え2

これが効果ですset -u

$#関数の内部を確認して$1設定されていない場合は、参照を回避できます。

$#これにより、複数のパラメータにアクセスできます。グローバルコンテキストではスクリプトの引数の数、関数では関数の引数の数です。

質問の文脈では、次のようになります。

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

まず評価してから確認するので、[ $# -ge 1 ] && [ -n "$1" ]andを使用する必要があります。[ $# -ge 1 -a -n "$1" ]$1$#

答え3

他の答えはこの効果に言及しましたset -u。他の答えのどれも、set -u次のように元に戻すことはできませんset +u

$ echo $VAR  # nothing echoed below as VAR is unset:

$ set -u
$ echo $VAR
bash: VAR: unbound variable
$ set +u
$ echo $VAR  # nothing echoed below as VAR is unset:

答え4

これはbash設定の確認をバイパスし、次を使用できるため、次のようになります(最初の引数はすべての引数です。二重引用符で囲むと、値がないと完全に消えてキャプチャされません)。$1"$@"$1$@set -u

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

出力する2つの値の間に{space} {tab} {space}が出ず、{tab}だけが出るように残りの行も少し調整しました。本当に2つの見えないスペースが必要な場合は、awkuseに変更してくださいprintf "%s \t %s\n", $1, $5

関連情報