Bashシェルスクリプトの入力引数の存在を確認する


1339

入力引数の存在を確認する必要があります。次のスクリプトがあります

if [ "$1" -gt "-1" ]
  then echo hi
fi

私は得る

[: : integer expression expected

最初に入力引数1をチェックして、それが存在するかどうかを確認するにはどうすればよいですか?

回答:


2330

それは:

if [ $# -eq 0 ]
  then
    echo "No arguments supplied"
fi

$#変数は、あなたのスクリプトが渡された入力引数の数を教えてくれます。

または、引数が空の文字列かどうかを確認できます。

if [ -z "$1" ]
  then
    echo "No argument supplied"
fi

-z「$ 1」の拡大がヌル文字列であるかどうかスイッチがテストします。それがnull文字列の場合、本体が実行されます。


62
私はこのように、簡潔な構文で、POSIXでも受け入れられるようにしたいと思っています。[ -z "$1" ] && echo "No argument supplied" ワンライナーの方が簡単なので、私はワンライナーを好みます。それは使用する場合と比較して、チェック終了値にも高速ですif
JMベッカー

168
exit 1スクリプトが機能するために引数が必要な場合は、おそらくifブロック内のエコーの最後にを追加する必要があります。明白ですが、完全性については注目に値します。
msanford 2013

16
めったに役立ちませんが、最初の引数を初期化して空にすることは可能です。programname "" secondarg third$#チェックが明確に引数の数をチェックします。
Tripleee、2013年

39
noobの場合、特にスクリプト化されていない経歴を持つ人にとっては、これらのことについていくつかの特徴を述べることも重要です。また、開始と終了のブレースの後にスペースが必要であると述べたかもしれません。さもなければ、うまくいきません。私は自分自身がスクリプトの初心者(私はCのバックグラウンド出身です)で、難しい方法だと思いました。すべてを「そのまま」コピーすることを決めたときだけ、うまくいきました。そのとき、開始ブレースの後、終了ブレースの前にスペースを残さなければならないことに気付きました。
HighOnMeat 2013

72
オプションの引数の場合if [ ! -z "$1" ]; then ...
gcb '26

347

この方法を示す方が良いです

if [[ $# -eq 0 ]] ; then
    echo 'some message'
    exit 1
fi

引数が少なすぎる場合は、通常、終了する必要があります。


72
いいえ、そうではありません。これには通常必要なものがあり、通常(iirc)の方が妥当なテストをexit 1使用し[[ ]]ます。ですから、盲目的にコードを貼り付ける人にとっては、これがより良い答えです。
dshepherd

42
[]と[[]]の違いの詳細については、stackoverflow.com
questions / 3427872

104

場合によっては、ユーザーがスクリプトに引数を渡したかどうかを確認し、渡さなかった場合はデフォルト値に戻す必要があります。以下のスクリプトのように:

scale=${2:-1}
emulator @$1 -scale $scale

ここで、ユーザーがscale2番目のパラメーターとして渡していない場合、Androidエミュレーターを起動します。-scale 1デフォルトでます。${varname:-word}展開演算子です。他の拡張演算子もあります:

  • ${varname:=word}どのセットvarnameを返すのではなく、未定義しwordます。
  • ${varname:?message} どちらかが戻る varname、定義されていてnullでない場合にか、messageを出力してスクリプトを中止します(最初の例のように)。
  • ${varname:+word}これはwordvarnameが定義されていてnullでない場合にのみ返されます。それ以外の場合はnullを返します。

1
上記の例ではを使用しているよう${varname?message}です。追加:はタイプミスですか、それとも動作が変わりますか?
Eki

6
えき、「:」は組み込みコマンドであり、この例では/ bin / trueの省略形です。それは基本的に提供される引数を無視する何もしないコマンドを表します。このテストでは、インタプリタが「$ varname」の内容を実行しようとしないようにするために不可欠です(これは確かに発生しません)。また、注目に値します。このメソッドを使用すると、必要な数の変数をテストできます。そして、すべて特定のエラーメッセージが表示されます。ie: ${1?"First argument is null"} ${2?"Please provide more than 1 argument"}
user.friendly 2017

48

試してください:

 #!/bin/bash
 if [ "$#" -eq  "0" ]
   then
     echo "No arguments supplied"
 else
     echo "Hello world"
 fi

4
なぜあなたは二重引用符が必要なのか$#0
user13107 14

1
$#や0のように二重引用符なしで使用しても問題ありません
Ranjithkumar T

Windowsでは、mingwこれが唯一の方法です。
Lajos Meszaros

2
この回答は、先ほど作成したスクリプトの優れた出発点となります。elseも見せてくれてありがとう。
クリスK

2
@ user13107 bashで二重引用符で囲まれた変数は、グロビング(つまり、のようなファイル名の拡張foo*)および単語分割(つまり、値に空白が含まれている場合は内容を分割)を防ぎます。この場合$#、両方のケースが適用されないため、引用する必要はありません。を引用する0必要もありませんが、実際には文字列であり、より明示的になるため、値を引用することを好む人もいます。
デニス

39

引数がスクリプトに渡されたかどうかを検出する別の方法:

((!$#)) && echo No arguments supplied!

これ(( expr ))により、式がShell Arithmeticのルールに従って評価されることに注意してください。

引数なしで終了するには、次のように言うことができます。

((!$#)) && echo No arguments supplied! && exit 1

上記を表すもう1つの(類似した)方法は次のとおりです。

let $# || echo No arguments supplied

let $# || { echo No arguments supplied; exit 1; }  # Exit if no arguments!

help let 言う:

let: let arg [arg ...]

  Evaluate arithmetic expressions.

  ...

  Exit Status:
  If the last ARG evaluates to 0, let returns 1; let returns 0 otherwise.

2
-1引数の存在を検証する場合、これは最悪の方法になる可能性があります。さらに、履歴の置換をトリガーし、潜在的に悪いことを行う可能性があります。
user.friendly 2017

2
exit私のzshプロセスを殺す代わりに、それreturnは殺さないwhich を使用します
Timo

なぜ((!$#))履歴置換がトリガーされるのですか?
Zhro、

25

私はこのスニペットを単純なスクリプトによく使用します。

#!/bin/bash

if [ -z "$1" ]; then
    echo -e "\nPlease call '$0 <argument>' to run this command!\n"
    exit 1
fi

1
だから、これはあなたが1つの引数だけを必要とするときに使用されますか?
Danijel

21

指摘すべきより多くの基本的なポイントがあるためだけに、文字列がnullかどうかを簡単にテストできることを付け加えます。

if [ "$1" ]; then
  echo yes
else
  echo no
fi

同様に、argカウントを期待している場合は、最後のものをテストしてください。

if [ "$3" ]; then
  echo has args correct or not
else
  echo fixme
fi

argまたはvarで


4

引数が存在するかどうかを確認する場合は、引数の数がターゲット引数番号以上かどうかを確認できます。

次のスクリプトは、これがどのように機能するかを示しています

test.sh

#!/usr/bin/env bash

if [ $# -ge 3 ]
then
  echo script has at least 3 arguments
fi

次の出力を生成します

$ ./test.sh
~
$ ./test.sh 1
~
$ ./test.sh 1 2
~
$ ./test.sh 1 2 3
script has at least 3 arguments
$ ./test.sh 1 2 3 4
script has at least 3 arguments

3

小さなリマインダーとして、バッシュの数値テスト演算子が整数のみで作業(-eq-lt-ge、など)

$ varsがintであることを確認したい

var=$(( var + 0 ))

私がそれらをテストする前に、「[:integer arg required」エラーから守るためだけに。


1
きちんとしたトリックですが、注意してください:bashは算術演算で浮動小数点数を処理できないため、このメソッドは構文エラーを引き起こし、ゼロ以外を返す可能性があります。 var=$(printf "%.0f" "$var")floatを処理できますが、文字列が指定された場合にゼロ以外の終了が発生します。awkを気にしない場合、私が使用するこの方法は、整数を強制するための最も堅牢なようです:var=$(<<<"$var" awk '{printf "%.0f", $0}')。varが設定されていない場合、デフォルトは "0"です。varがfloatの場合、最も近い整数に丸められます。負の値も使用できます。
user.friendly 2017

0

ワンライナーbash関数の検証

myFunction() {

    : ${1?"forgot to supply an argument"}
    if [ "$1" -gt "-1" ]; then
        echo hi
    fi

}

関数名と使用法を追加

myFunction() {

    : ${1?"forgot to supply an argument ${FUNCNAME[0]}() Usage:  ${FUNCNAME[0]} some_integer"}
    if [ "$1" -gt "-1" ]; then
        echo hi
    fi

}

整数かどうかをチェックする検証を追加

追加の検証を追加するには、たとえば、渡された引数が整数かどうかを確認するために、検証関数を呼び出して検証関数を呼び出すようにします。

: ${1?"forgot to supply an argument ${FUNCNAME[0]}() Usage:  ${FUNCNAME[0]} some_integer"} && validateIntegers $1 || die "Must supply an integer!"

次に、引数を検証する検証関数を作成し、成功した場合は0、失敗した場合は1、失敗した場合はスクリプトを中止するdie関数を作成します

validateIntegers() {

    if ! [[ "$1" =~ ^[0-9]+$ ]]; then
        return 1 # failure
    fi
    return 0 #success

}

die() { echo "$*" 1>&2 ; exit 1; }

さらにシンプル-使用するだけ set -u

set -u 参照されるすべての変数が使用時に設定されていることを確認するので、設定して忘れてください

myFunction() {
    set -u
    if [ "$1" -gt "-1" ]; then
        echo hi
    fi

}
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.