GNU/Linux >> Linux の 問題 >  >> Linux

Bashスクリプトに引数とオプションを追加する

ほとんどのシステム管理者にとって最も重要なツールの1つは、自動化です。スクリプトを作成して維持し、実行する必要のある一般的で頻繁なタスクを自動化します。

何十年にもわたって作成および変更した、短いスクリプトと長いスクリプトがあります。私の最も便利なスクリプトのいくつかは、毎朝早朝に定期的なバックアップを実行し、修正と拡張機能を備えた更新されたソフトウェアパッケージをインストールし、Fedoraのあるバージョンから次のバージョンにアップグレードすることです。かなり単純なスクリプトを使用して、数日前にすべての個人用ホストとサーバーをFedora34にアップグレードしました。

[次のこともお勧めします:もっと愚かなBashのトリック:変数、検索、ファイル記述子、リモート操作]

すべてのスクリプトに対して私が行う最も一般的な2つのことは、ヘルプ関数とGPL3ライセンスステートメントを表示する関数を作成することです。スクリプトの問題判別を支援するために、冗長モードまたはテストモードを含めるのが好きです。一部のスクリプトでは、ユーザー名、アップグレード先のFedoraのバージョン、ファイル名などの値も渡します。

スクリプト内の変数の値として使用されるデータを指定するために、位置パラメーター(引数とも呼ばれます)を使用する機能は、これを実現するための1つの方法です。もう1つは、オプションとオプション引数の使用です。この記事では、データをスクリプトに取り込み、スクリプトの実行パスを制御するためのこれら2つの方法について説明します。

位置パラメータ

Bashは、位置パラメーターと呼ばれるツールを使用して、コマンドラインから呼び出されたときにBashプログラムにデータを入力する手段を提供します。 $ 0から実行される10個の位置パラメータがあります $ 9まで 、その制限を回避する方法はありますが。

入力した名前を画面に表示する簡単なスクリプトから始めます。 script1.shというファイルを作成します 次のコンテンツを使用して実行可能にします。

#!/bin/bash
echo $0

このスクリプトを~/bin directoryに配置しました 、スクリプトなどの個人用実行可能ファイルを保存することを目的としています。 $ PATHを見てください /home/username/binを含む変数 1つのコンポーネントとして。 ~/binの場合 ディレクトリが存在しない場合は、作成できます。または、このファイルを好きな場所に置いて、そこから使用することもできます。

次に、パラメータなしでスクリプトを実行します。

[student@testvm1 ~]$ script1.sh
/home/dboth/bin/script1.sh
[student@testvm1 ~]$

このスクリプトからの出力は、スクリプトの名前です。 $ 0 パラメーターは予約されており、実行中のスクリプトの名前として事前定義されており、他の目的に使用することはできません。必要に応じてスクリプトに独自の名前を渡す必要がないため、これはスクリプト内で便利です。

したがって、 $ 1を使用するようにスクリプトを変更してください 位置変数の場合は、もう一度実行します:

#!/bin/bash
echo $1

今回は単一のパラメータを使用して、もう一度実行します:

[student@testvm1 ~]$ script1.sh help
help
[student@testvm1 ~]$

パラメータが2語の場合はどうなりますか?

[student@testvm1 ~]$ script1.sh help me
help
[student@testvm1 ~]$

これは実際には2つのパラメータですが、次のように引用符で修正できます:

[student@testvm1 ~]$ script1.sh "help me"
help me
[student@testvm1 ~]$

これは、次のように、入力が番地または複数の単語を含むものであると想定される場合に役立ちます。

[student@testvm1 ~]$ script1.sh "80486 Intel St."
80486 Intel St.
[student@testvm1 ~]$

ただし、名前や完全な住所など、複数のパラメータが必要になる場合があります。

プログラムを次のように変更します:

#!/bin/bash
echo "Name: $1"
echo "Street: $2"
echo "City: $3"
echo "State/Province/Territory: $4"
echo "Zip/Postal code: $5"

そして、示されているパラメータを使用して実行します:

[student@testvm1 ~]$ script1.sh "David Both" "80486 Intel St." Raleigh NC XXXXX
Name: David Both
Street: 80486 Intel St.
City: Raleigh
State/Province/Territory: NC
Zip/Postal code: XXXXX

もちろん、値が割り当てられた後、位置パラメータを使用する方法はたくさんありますが、この小さなプログラムを使用すると、何が起こっているかを簡単に確認できます。また、安全な方法での実験も簡単になります。

パラメータを別の順序で配置して、それがどのように機能するかを確認してください。これらのパラメーターは定位置であり、これが重要な考慮事項です。必要なパラメーターの数、ユーザーがそれらをどのように覚えているか、およびそれらを配置する順序を考慮する必要があります。

パラメータの順序を無関係にする方法が必要ですが、それでも実行パスを変更する方法が必要です。

オプション

コマンドラインオプションを使用して、これら2つのことを実行できます。

たとえそれがかなり初歩的なものであったとしても、単純なBashプログラムでさえある種のヘルプ機能を備えているべきだと私は思います。私が作成するBashシェルプログラムの多くは、使用頻度が低いため、発行する必要のあるコマンドの正確な構文を忘れてしまう可能性があります。非常に複雑なものもあるので、頻繁に使用しているにもかかわらず、必要なオプションと引数を確認する必要があります。

ヘルプ機能が組み込まれているため、コード自体を検査しなくても、これらを表示できます。優れた完全なヘルプ機能も、プログラムドキュメントの一部です。

関数について

シェル関数は、シェルの環境に格納されているBashプログラムステートメントのリストであり、コマンドラインで名前を入力することにより、他のコマンドと同じように実行できます。シェル関数は、使用している可能性のある他のプログラミング言語に応じて、プロシージャまたはサブルーチンとも呼ばれます。

関数は、他のコマンドの場合と同じように、スクリプト内またはCLIから名前を使用して呼び出されます。 CLIプログラムまたはスクリプトでは、関数内のコマンドは呼び出されたときに実行されます。次に、一連のプログラムフローが呼び出し元のエンティティに戻り、そのエンティティ内の次の一連のプログラムステートメントが実行されます。

関数の構文は次のとおりです。

FunctionName(){プログラムステートメント}

CLIで簡単な関数を作成します。関数は、それが作成されたシェルインスタンスのシェル環境に保存されます。 hwという関数を作成します 、 Hello worldの略です 。 CLIで次のコードを入力し、 Enterを押します。 。次に、 hwと入力します 他のシェルコマンドと同じように。

[student@testvm1 ~]$ hw(){ echo "Hi there kiddo"; }
[student@testvm1 ~]$ hw
Hi there kiddo
[student@testvm1 ~]$

さて、私は標準の「Helloworld!」に少しうんざりしています。私は通常、から始めます。次に、現在定義されているすべての関数を一覧表示します。それらはたくさんあるので、新しい hwだけを示しました 働き。コマンドラインから、またはプログラム内で呼び出されると、関数はプログラムされたタスクを実行します。次に終了し、呼び出し元のエンティティ、コマンドライン、または呼び出し元のステートメントの後のスクリプト内の次のBashプログラムステートメントに制御を戻します。

[student@testvm1 ~]$ declare -f | less
<snip>
hw ()
{
    echo "Hi there kiddo"
}
<snip>

もう必要ないので、その関数を削除します。 unsetでそれを行うことができます 次のようなコマンド:

[student@testvm1 ~]$ unset -f hw ; hw
bash: hw: command not found
[student@testvm1 ~]$

hello.shスクリプト

新しいBashシェルスクリプト~/bin/hello.shを作成します 、実行可能にします。次のコンテンツを追加し、基本的な開始を維持します。

#!/bin/bash
echo "hello world!"

これを実行して、「helloworld!」が出力されることを確認します。

[dboth@david ~]$ hello.sh
hello world!
[dboth@david ~]$

私は知っています—私は自分自身を助けることができないので、「helloworld!」に戻りました。

ヘルプ機能の作成

ヘルプを追加します helloプログラムのコードに以下に示す関数。 ヘルプを配置します すでに持っている2つのステートメントの間で機能します。このヘルプ 関数は、プログラムの簡単な説明、構文図、および使用可能な各オプションの簡単な説明を表示します。また、ヘルプへの呼び出しを追加します それをテストするための関数と、関数とプログラムの主要部分との間の視覚的な境界を提供するいくつかのコメント行。

プログラムは次のようになります。

#!/bin/bash
############################################################
# Help                                                     #
############################################################
Help()
{
   # Display Help
   echo "Add description of the script functions here."
   echo
   echo "Syntax: scriptTemplate [-g|h|v|V]"
   echo "options:"
   echo "g     Print the GPL license notification."
   echo "h     Print this Help."
   echo "v     Verbose mode."
   echo "V     Print software version and exit."
   echo
}

############################################################
############################################################
# Main program                                             #
############################################################
############################################################

Help
echo "Hello world!"

このヘルプで説明されているオプション 私が書いたプログラムでは、関数は典型的なものかもしれませんが、コードにはまだ存在していません。プログラムを実行してテストします。

[student@testvm1 ~]$ hello.sh
Add a description of the script functions here.

Syntax: scriptTemplate [-g|h|v|V]
options:
g     Print the GPL license notification.
h     Print this Help.
v     Verbose mode.
V     Print software version and exit.

Hello world!
[student@testvm1 ~]$

必要なときにヘルプを表示するロジックを追加していないため、プログラムは常にヘルプを表示します。ただし、関数が正しく機能していることはわかっているため、-hを使用する場合にのみ、ヘルプを表示するためのロジックを追加できます。 プログラムのコマンドライン呼び出しでのオプション。

処理オプション

-hなどのコマンドラインオプションを処理するBashスクリプトの機能 ヘルプを表示すると、プログラムを指示し、プログラムの動作を変更するための強力な機能が提供されます。 -hの場合 オプションで、プログラムがヘルプテキストをターミナルセッションに出力してから、プログラムの残りの部分を実行せずに終了するようにします。コマンドラインで入力されたオプションを処理する機能は、whileを使用してBashスクリプトに追加できます。 getopsと組み合わせたコマンド およびcase コマンド。

getops commandは、コマンドラインで指定されたすべてのオプションを読み取り、それらのオプションのリストを作成します。 while コマンドは、変数 $ options を設定することにより、オプションのリストをループします。 以下のコードのそれぞれについて。 case ステートメントは、各オプションを順番に評価し、対応するスタンザのステートメントを実行するために使用されます。 while ステートメントは、オプションのリストがすべて処理されるか、終了ステートメントが検出されてプログラムが終了するまで、オプションのリストを評価し続けます。

必ずヘルプを削除してください echo "Hello world!"の直前の関数呼び出し プログラムの本体が次のようになるようにステートメントを記述します。

############################################################
############################################################
# Main program                                             #
############################################################
############################################################
############################################################
# Process the input options. Add options as needed.        #
############################################################
# Get the options
while getopts ":h" option; do
   case $option in
      h) # display Help
         Help
         exit;;
   esac
done

echo "Hello world!"

-hのcaseオプションのexitステートメントの最後にある二重セミコロンに注意してください。 。これは、オプションごとに必要です。このcaseステートメントに追加して、各オプションの終わりを示します。

テストはもう少し複雑になりました。プログラムがどのように応答するかを確認するには、いくつかの異なるオプションを使用して(オプションを使用せずに)プログラムをテストする必要があります。まず、「Helloworld!」と表示されるオプションがないことを確認します。必要に応じて。

[student@testvm1 ~]$ hello.sh
Hello world!

これでうまくいくので、ヘルプテキストを表示するロジックをテストします。

[student@testvm1 ~]$ hello.sh -h
Add a description of the script functions here.

Syntax: scriptTemplate [-g|h|t|v|V]
options:
g     Print the GPL license notification.
h     Print this Help.
v     Verbose mode.
V     Print software version and exit.

これは期待どおりに機能するため、テストを試して、予期しないオプションを入力したときに何が起こるかを確認してください。

[student@testvm1 ~]$ hello.sh -x
Hello world!
[student@testvm1 ~]$ hello.sh -q
Hello world!
[student@testvm1 ~]$ hello.sh -lkjsahdf
Add a description of the script functions here.

Syntax: scriptTemplate [-g|h|t|v|V]
options:
g     Print the GPL license notification.
h     Print this Help.
v     Verbose mode.
V     Print software version and exit.

[student@testvm1 ~]$

無効なオプションの処理

プログラムは、エラーを生成せずに特定の応答を作成していないオプションを無視します。 -lkjsahdfの最後のエントリにありますが オプション。リストに「h」があるため、プログラムはそれを認識し、ヘルプテキストを出力しました。テストの結果、不足しているのは、誤った入力を処理し、検出された場合にプログラムを終了する機能であることがわかっています。

明示的に一致しないオプションに一致する別のcaseスタンザをcaseステートメントに追加できます。この一般的なケースは、特定の一致を提供していないものと一致します。 ケース ステートメントは次のようになります。

while getopts ":h" option; do
   case $option in
      h) # display Help
         Help
         exit;;
     \?) # Invalid option
         echo "Error: Invalid option"
         exit;;
   esac
done

このコードのビットは、それがどのように機能するかについての説明に値します。複雑に見えますが、かなり理解しやすいです。 while – done 構造体は、 getopts –オプションのオプションごとに1回実行されるループを定義します 構造。 ":h" 文字列(引用符が必要)には、 case – esacによって評価される可能性のある入力オプションが一覧表示されます。 構造。リストされている各オプションには、caseステートメントに対応するスタンザが含まれている必要があります。この場合、2つあります。 1つはh) ヘルププロシージャを呼び出すスタンザ。ヘルプ手順が完了すると、実行は次のプログラムステートメント exit;;に戻ります。 これは、コードが存在する場合でも、それ以上コードを実行せずにプログラムを終了します。オプション処理ループも終了するため、追加のオプションはチェックされません。

\?のキャッチオールマッチに注目してください caseステートメントの最後のスタンザとして。認識されないオプションが入力された場合、このスタンザは短いエラーメッセージを出力し、プログラムを終了します。

追加の特定のケースは、最後のキャッチオールの前に行う必要があります。ケーススタンザをアルファベット順に配置するのが好きですが、特定のケースが他の特定のケースよりも先に処理されるようにしたい場合があります。 caseステートメントはシーケンスに依存するため、作成するときはそのことに注意してください。

case構文の各スタンザの最後のステートメントは、二重セミコロン(;;)で終了する必要があります。 )。これは、各スタンザの終わりを明示的にマークするために使用されます。これにより、暗黙的なセミコロンではなく、各ステートメントの最後に明示的なセミコロンを使用したいプログラマーは、各ケーススタンザ内の各ステートメントに対して引き続き使用できます。

以前と同じオプションを使用してプログラムを再度テストし、これがどのように機能するかを確認します。

Bashスクリプトは次のようになります。

#!/bin/bash
############################################################
# Help                                                     #
############################################################
Help()
{
   # Display Help
   echo "Add description of the script functions here."
   echo
   echo "Syntax: scriptTemplate [-g|h|v|V]"
   echo "options:"
   echo "g     Print the GPL license notification."
   echo "h     Print this Help."
   echo "v     Verbose mode."
   echo "V     Print software version and exit."
   echo
}

############################################################
############################################################
# Main program                                             #
############################################################
############################################################
############################################################
# Process the input options. Add options as needed.        #
############################################################
# Get the options
while getopts ":h" option; do
   case $option in
      h) # display Help
         Help
         exit;;
     \?) # Invalid option
         echo "Error: Invalid option"
         exit;;
   esac
done


echo "hello world!"

このバージョンのプログラムを徹底的にテストしてください。ランダム入力を使用して、何が起こるかを確認します。また、ダッシュ(-)を使用せずに、有効なオプションと無効なオプションをテストしてみてください。 )前に。

オプションを使用してデータを入力する

まず、変数を追加して初期化します。以下に示すプログラムのセグメントに、太字で示されている2行を追加します。これにより、 $ Nameが初期化されます デフォルトとして「world」への変数。

<snip>
############################################################
############################################################
# Main program                                             #
############################################################
############################################################

# Set variables
Name="world"

############################################################
# Process the input options. Add options as needed.        #
<snip>

プログラムの最後の行であるechoを変更します コマンド、これに。

echo "hello $Name!"

すぐに名前を入力するロジックを追加しますが、最初にプログラムを再度テストします。結果は以前とまったく同じになるはずです。

[dboth@david ~]$ hello.sh
hello world!
[dboth@david ~]$
# Get the options
while getopts ":hn:" option; do
   case $option in
      h) # display Help
         Help
         exit;;
      n) # Enter a name
         Name=$OPTARG;;
     \?) # Invalid option
         echo "Error: Invalid option"
         exit;;
   esac
done

$ OPTARG は、いくつあっても、常に新しいオプション引数ごとに使用される変数名です。 $ OPTARGで値を割り当てる必要があります プログラムの残りの部分で使用される変数名に。この新しいスタンザには、exitステートメントがありません。これにより、プログラムフローが変更され、caseステートメント内のすべての有効なオプションが処理された後、実行がcase構文の次のステートメントに移動します。

改訂されたプログラムをテストします。

[dboth@david ~]$ hello.sh
hello world!
[dboth@david ~]$ hello.sh -n LinuxGeek46
hello LinuxGeek46!
[dboth@david ~]$ hello.sh -n "David Both"
hello David Both!
[dboth@david ~]$

完成したプログラムは次のようになります。

#!/bin/bash
############################################################
# Help                                                     #
############################################################
Help()
{
   # Display Help
   echo "Add description of the script functions here."
   echo
   echo "Syntax: scriptTemplate [-g|h|v|V]"
   echo "options:"
   echo "g     Print the GPL license notification."
   echo "h     Print this Help."
   echo "v     Verbose mode."
   echo "V     Print software version and exit."
   echo
}

############################################################
############################################################
# Main program                                             #
############################################################
############################################################

# Set variables
Name="world"

############################################################
# Process the input options. Add options as needed.        #
############################################################
# Get the options
while getopts ":hn:" option; do
   case $option in
      h) # display Help
         Help
         exit;;
      n) # Enter a name
         Name=$OPTARG;;
     \?) # Invalid option
         echo "Error: Invalid option"
         exit;;
   esac
done


echo "hello $Name!"

ヘルプ機能と、プログラムが無効な入力にどのように反応するかをテストして、それらを処理する能力が損なわれていないことを確認してください。それがすべて正常に機能する場合は、オプションとオプション引数の使用方法を正常に学習しています。

[この無料の電子書籍を入手する:ダミーのKubernetesクラスターを管理する。 ]

まとめ

この記事では、位置パラメーターを使用して、コマンドラインからの呼び出し中にBashプログラムにデータを入力し、オプションを使用して、プログラムのフローを指示したり、プログラムにデータを入力したりしました。ヘルプ機能と、ヘルプを選択的に表示するコマンドラインオプションを処理する機能を追加しました。また、コマンドラインで名前を入力できるオプションの引数を追加しました。

この小さなテストプログラムはシンプルに設計されているため、自分で簡単に実験して、この入力方法を自分でテストできます。演習として、プログラムを修正して、名と姓を取得します。名前と名前のオプションを逆の順序で入力して、何が起こるかを確認してください。

リソース

  • Bashでプログラミングする方法:構文とツール
  • Bashでプログラミングする方法:論理演算子とシェル拡張
  • Bashでプログラミングする方法:ループ

Linux
  1. シェルスクリプトで入力を使用する方法

  2. スクリプトとscriptreplayを使用して端末を記録します

  3. bash スクリプトを使用した telnet セッションの自動化

  1. Bashでは、いつエイリアスを作成し、いつスクリプトを作成し、いつ関数を作成するのですか?

  2. スクリプト内の bash シェル スクリプトおよび関数の変数スコープ

  3. bash スクリプトのコマンドとターミナルのコマンドの違い

  1. コマンドライン引数をBashスクリプトに渡しますか?

  2. Bashスクリプトに.shまたは.bash拡張子を使用しますか?

  3. BashスクリプトをBashにパイプするときにパラメータを設定する方法は?