オプションの入力引数を取るbashスクリプトを作成する方法は?


471

スクリプトでオプションの入力を取得できるようにしたい

たとえば、現在私のスクリプトは

#!/bin/bash
somecommand foo

しかし、私はそれを言いたいと思います:

#!/bin/bash
somecommand  [ if $1 exists, $1, else, foo ]

3
BashまたはPOSIX?Bashには、より多くの可能性があります
user123444555621

@ Pumbaa80 bash-タグを更新しました。
阿部


回答:


706

デフォルト値の構文を使用できます。

somecommand ${1:-foo}

上記は、Bashリファレンスマニュアル-3.5.3シェルパラメータの展開で説明されているように[強調]

パラメータが設定されていないかnullの場合、単語の展開が置換されます。それ以外の場合は、パラメーターの値が置き換えられます。

パラメータが設定されていない場合にのみデフォルト値を置き換えたい場合(ただし、空文字列でない場合など、nullでない場合)、代わりに次の構文を使用します。

somecommand ${1-foo}

再びから3.5.3シェルパラメータ拡大-バッシュリファレンスマニュアル

コロンを省略すると、設定されていないパラメーターのみがテストされます。言い換えると、コロンが含まれている場合、演算子は両方のパラメーターの存在と、その値がnullではないことをテストします。コロンが省略されている場合、オペレーターは存在のみをテストします。


52
「戻り、上記のコマンド間の意味の違いに注意してくださいfoo場合は$1設定されていないか、空の文字列」、および${1-foo}、「リターンfoo場合は、$1設定されていません」。
l0b0

12
これが機能する理由を説明できますか?特に、「:」と「-」の機能/目的は何ですか?
jwien001 2014

8
@ jwein001:上記の回答では、変数が定義されていない場合、置換演算子を使用してデフォルト値が返されます。具体的には、ロジックは「$ 1が存在し、nullでない場合はその値を返し、それ以外の場合はfooを返す」です。コロンはオプションです。省略した場合は、「存在し、nullではない」を「存在する」のみに変更してください。マイナス記号は、$ 1を「foo」に設定せずにfooを返すことを指定します。置換演算子は、拡張演算子のサブクラスです。RobbinsおよびBeebeのクラシックシェルスクリプティングのセクション6.1.2.1 [O'Reilly](shop.oreilly.com/product/9780596005955.do)を参照
Jubbles

5
@Jubbles、または単純な参照用に本全体を購入したくない場合... tldp.org/LDP/abs/html/parameter-substitution.html
Ohad Schneider

2
@hagenが行うように、デフォルトをコマンドの実行結果にする方法を示した場合、この回答はさらに優れたものになります(回答はエレガントではありません)。
ソウトマン

310

次のように、変数のデフォルト値を設定できます。

somecommand.sh

#!/usr/bin/env bash

ARG1=${1:-foo}
ARG2=${2:-bar}
ARG3=${3:-1}
ARG4=${4:-$(date)}

echo "$ARG1"
echo "$ARG2"
echo "$ARG3"
echo "$ARG4"

これがどのように機能するかの例をいくつか示します。

$ ./somecommand.sh
foo
bar
1
Thu Mar 29 10:03:20 ADT 2018

$ ./somecommand.sh ez
ez
bar
1
Thu Mar 29 10:03:40 ADT 2018

$ ./somecommand.sh able was i
able
was
i
Thu Mar 29 10:03:54 ADT 2018

$ ./somecommand.sh "able was i"
able was i
bar
1
Thu Mar 29 10:04:01 ADT 2018

$ ./somecommand.sh "able was i" super
able was i
super
1
Thu Mar 29 10:04:10 ADT 2018

$ ./somecommand.sh "" "super duper"
foo
super duper
1
Thu Mar 29 10:05:04 ADT 2018

$ ./somecommand.sh "" "super duper" hi you
foo
super duper
hi
you

2
あ、そう。-(それは否定のですか?)私を混同しました。
Raffi Khatchadourian 2018年

5
いいえ。これは、bashが割り当てを行う際の奇妙な方法です。これを少し明確にするために、さらにいくつかの例を追加します...ありがとう!
Brad Parks

44
if [ ! -z $1 ] 
then 
    : # $1 was given
else
    : # $1 was not given
fi

1
技術的には、パラメーターとしてカウントされる可能性がある空の文字列 ''を渡すと、チェックでそれが失われます。その場合、$#は与えられたパラメーターの数を示します
vmpstr

18
-nと同じ! -zです。
l0b0

を使用-n! -zて異なる結果が得られるため、ここではそうではありません。
Eliezer

変数の引用に失敗したため、[ -n $1 ] 常にtrueになります。bashを使用[[ -n $1 ]]すると、期待どおりに動作します。それ以外の場合は引用する必要があります[ -n "$1" ]
glenn jackman


10

変数$ 1 .. $ nの場合、置換を使用するには通常の変数に書き込む必要があることを忘れないでください。

#!/bin/bash
NOW=$1
echo  ${NOW:-$(date +"%Y-%m-%d")}

2
上記のブラッドの答えは、引数変数も中間変数なしで置換できることを証明しています。
Vadzim 2016年

2
デフォルトとして、固定値の代わりに日付などのコマンドを使用する方法を示すための+1。また、これは可能である:DAY=${1:-$(date +%F -d "yesterday")}
ギャレンS

3

オプションの複数の引数の場合、ls1つ以上のファイルを取得できるコマンドと同様に、またはデフォルトで現在のディレクトリ内のすべてをリストします。

if [ $# -ge 1 ]
then
    files="$@"
else
    files=*
fi
for f in $files
do
    echo "found $f"
done

残念ながら、パスにスペースが含まれているファイルでは正しく機能しません。まだどのように機能するかを理解していません。


2

これにより、オプションの1番目の引数のデフォルト値が許可され、複数の引数が保持されます。

 > cat mosh.sh
   set -- ${1:-xyz} ${@:2:$#} ; echo $*    
 > mosh.sh
   xyz
 > mosh.sh  1 2 3
   1 2 3 

1

変数置換を使用して、固定値またはコマンド(などdate)を引数に置き換えることができます。これまでの答えは固定値に焦点を当てていましたが、これは日付をオプションの引数にするために使用したものです:

~$ sh co.sh
2017-01-05

~$ sh co.sh 2017-01-04
2017-01-04

~$ cat co.sh

DAY=${1:-$(date +%F -d "yesterday")}
echo $DAY
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.