スクリプトに引数を渡す

スクリプトに引数を渡す

私は Linux Essentials クラスを受講しており、スクリプトの章までは順調でした。しかし、これらの概念がまったく理解できません。次の内容を非常に単純な言葉で説明してくれる人や、学習に役立つ参考資料を教えてくれる人はいませんか。現在、netacad のカリキュラムを使用しています。


教科書から(若干の書式変更あり):

設定した変数に加えて、いくつかの特別な変数があります。スクリプトに引数を渡すことができます。

#!/bin/bash
echo "Hello $1"

ドル記号の後に数字 N が続くものは、スクリプトに渡される N 番目の引数に対応します。上記の例を呼び出すと、./test.sh出力は Hello Linux になります。$0変数にはスクリプト自体の名前が含まれます。

プログラムが実行されると、バイナリでもスクリプトでも、0 から 255 までの整数の終了コードが返されます$?。変数を使用してこれをテストし、前のコマンドが正常に完了したかどうかを確認できます。


変数を割り当てる方法と、それが でどのように機能するかは理解していますが、と$に関する全体的な問題がまったくわかりません。 $0$1

どのような助けでも大歓迎です。

答え1

この本の説明は間違っています (または少なくとも何かが欠けています)。そのスクリプトで「Hello Linux」と印刷するには、次のように実行します。

./test.sh Linux

だけを指定して実行すると./test.sh、最初の引数がなく、 が定義されていないため、「Hello 」のみが出力されます$1。一方、次のように実行したとします。

./test.sh foo bar baz

スクリプト内では、$0"./test.sh"、$1"foo"、$2"bar"、$3"baz" になります。

については$?、次のスクリプト スニペットを検討してください。

ls nonexistentfile.txt
echo "The exit status of ls was: $?"
echo "The exit status of echo (the first one) was: $?"

実行すると、次のような内容が出力されます:

ls: nonexistentfile.txt: No such file or directory
The exit status of ls was: 1
The exit status of echo (the first one) was: 0

このlsコマンドは、nonexistentfile.txt をリストできません (存在しないため)。そのため、その旨のエラー メッセージを出力し、何か問題が発生したことを示す 0 以外のステータスで終了します。最初のコマンドは、echoその終了ステータス ( $?) を出力し、正常に終了したため、0 のステータスで終了します。2 番目のコマンドが実行されると、最初のコマンドからecho取得されるため、「0」が出力されます。$?echo

ところで、多くのコマンドは0(成功)または1(何らかの失敗)の終了ステータスを使用しますが、いくつかのコマンドは何が間違っていたかを正確に示すために異なる失敗ステータスを使用します。以下はcurlマニュアルページ:

EXIT CODES
       There are a bunch of different  error  codes  and  their  corresponding
       error  messages  that  may appear during bad conditions. At the time of
       this writing, the exit codes are:

       1      Unsupported protocol. This build of curl has no support for this
              protocol.

       2      Failed to initialize.

       3      URL malformed. The syntax was not correct.

       ...

       88     FTP chunk callback reported error

       89     No connection available, the session will be queued

       90     SSL public key does not matched pinned public key

       91     Invalid SSL certificate status.

       92     Stream error in HTTP/2 framing layer.

...そのため、スクリプトを使用して何が問題なのかを確認し、問題に応じて異なる対応をとることcurlができます。$?

答え2

$0は、スクリプトを実行するために使用する名前です。$1、、$2などはスクリプトの位置パラメータであり、スクリプトを実行したときに渡したコマンドライン引数の値を保持します。

としてゴードン・デイヴィソンは言ったの場合、本の著者は、 を実行すると が./test Linux出力されると言いたかったに違いありませんHello Linux。その場合、./testは特殊パラメータ に入り0Linuxは最初の位置パラメータ に入ります。スクリプトは、変数の場合と同じように、1その最初の位置パラメータの前にドル記号 ( ) を付けて展開します。 代わりに を実行した場合、スクリプトでは、は に、は に、は に、は に展開されます。$1./test Hello Linux for Human Beings$1Linux$2for$3Human$4Beings

これを試すには、簡単なスクリプトを記述します。

#!/bin/bash

echo "\$0 expands to '$0'."
echo "\$1 expands to '$1'."
echo "\$2 expands to '$2'."
echo "\$3 expands to '$3'."

(好きなだけ続けてください。 より大きい位置パラメータの場合は9${ }パラメータ展開の形式を使用します。たとえば、 と10記述して展開します${10}。多くの位置パラメータを扱うスクリプトでは、繰り返しを避けるために特殊な パラメータ@がよく使用されますが、必要に応じて今のところはそれを無視できます。)

これをファイルに保存し、ファイルを実行可能としてマークしてみてください。これは、 を実行して実行できます。chmod +x simpleここで、 はファイル名に置き換えられます (ファイル名が異なる場合)。その後、、、などsimpleのコマンドを使用して実行できます。./simple./simple foo./simple foo bar

3 つ未満のコマンドライン引数が渡された場合、渡されなかった引数に対応する位置パラメータが空の文字列に展開されることに気付くでしょう。これは、定義されていないシェル パラメータを展開しようとすると発生します。さらに、より多くのコマンドライン引数が渡された場合、3 つ目以降の引数は使用されないことに気付くでしょう。スクリプトはそれらの引数をまったく参照しないので、これはおそらく予想どおりです。

次に、 を実行してみてください./simple *。シェルは、*で始まるファイル名を除く現在のディレクトリ内のすべてのファイル名に展開される.ため、そのうちの 3 つが最初の 3 つの位置パラメータとして表示されます (数がそれほど多くない場合は、それより少なく表​​示されます)。 などの他のシェル展開を使用して実行してみることもできます./simple {5..10}

空白を含むコマンドライン引数を引用符で囲むことで渡すことができます。たとえば、 を試してください。は だけでなく、今回は に展開される./simple 'foo bar' bazことに注意してください。$1foo barfoo

シェルはさまざまな拡張では、コマンドに渡すコマンドライン引数の数が必ずしも明らかではありません。各引数が何であるかを確認する簡単な方法は、コマンドを に置き換えることですprintf '[%s]\n'。例:

$ printf '[%s]\n' f*
[fonts]
[fstab]
[fuse.conf]
[fwupd]
$ printf '[%s]\n' {1,3}{a..c}
[1a]
[1b]
[1c]
[3a]
[3b]
[3c]

シェルスクリプトを始めたばかりなので、Bash リファレンスマニュアル難しいかもしれませんし、最初から最後まで読む気にはなれないかもしれません。しかし、完全な初心者であっても、この本は貴重なリソースだと思います。シェルパラメータすでに知っているシェル変数から始めて、?$?展開方法なのでパラメータと呼ばれることが多い)のような特別なパラメータに進むので便利です。Bashの一般的な学習、特に入門レベルでは、これらのページ、 含むバッシュガイド

答え3

知っておくべき良い本の一つは、ウィリアム・ショッツの「Linuxコマンドライン」です。これはNo Starch Pressから出版されており、無料のPDFとして入手できます。著者のウェブサイト

すべてのシェル スクリプトには、番号付きの変数のコレクションがあり、これらは一般に 、 などと呼ばれます$1$2これらは「位置パラメータ」であり、一般的にはコマンド ライン引数として知られています。これらは 、1などの名前の変数と考えることができ2、その値を取得するには 、 などを使用します$1。コマンド ライン 経由で$2という名前のスクリプトを呼び出すと、スクリプトは 3 つの変数、、に格納されている 3 つの引数を取得します。これらの変数に割り当てることはできません (グループとして割り当てる場合を除く) が、その値を調べて使用することはできます。たとえば、 はスクリプトの最初の引数を出力します。my_script./my_script a b c$1$2$3echo "$1"

$0は少し変わっています。これは、実行中のスクリプトが呼び出された名前です。上記の場合、値は になります./my_script。この場合も、その値を確認することはできますが、変更することはできません。

$?は、実行したばかりのコマンドの「終了ステータス」です。コマンドが成功した場合、その終了ステータスは になり0、そうでない場合は小さな正の整数になります。$?ゼロと比較することで、前のコマンドが成功したか失敗したかを確認できます。たとえば、次の 2 つのコマンド ラインは、コマンドを実行し、失敗したため、(失敗したことを示す) のステータスで終了したことをgrepエコーし​​ます。<1>grep1

grep blarg /etc/passwd
echo "<$?>"

終了ステータスは、次のような単純なスクリプトを書くときに役立ちます。

#!/bin/bash
# grep_pw: grep for a pattern in /etc/passwd
grep "$1" /etc/passwd
if [[ $? = 0 ]] ;then
  echo "Found it"
  exit 0
else
  echo "Unable to find the pattern '$1' in /etc/passwd"
  exit 1
fi

そのテキストを という名前のファイルに入れてgrep_pw、 で実行できるように変更しchmod 700 grep_pw、 のように呼び出して、で文字列 を含む./grep_pw nologin行を検索します。/etc/passwdnologin

初めてシェルについて学んだとき、シェルがコマンド ラインを解析する方法と、その結果スクリプトに渡されるコマンド ライン引数を理解するために、次のスクリプトが非常に役立つことがわかりました。

#!/bin/bash
# echoargs: print all the arguments
counter=1
for a in "$@" ;do
   echo "arg $counter=<$a>"
   let counter=counter+1
done

これらの内容を という名前のファイルに入れてechoargs、 で実行できるように変更しchmod 700 echoargs、 のように呼び出します./echoargs a "b c" d

関連情報