« 2008年6月 | メイン

2009年4月 アーカイブ

2009年4月 2日

シェル(Bash)の引数展開

シェル(Bash)の引数展開について、自分でも忘れがちなので記録を残しておこうと思います。


前置き

この文章では引数展開の例を記述しています。
前提として、カレントディレクトリに、以下のディレクトリとファイルがあるものとします。
first/here-is-first1.txt first/here-is-first2.txt second/here-is-second1.txt second/here-is-second2.txt second/here-is-second3.txt
また、この文章で用いたbashのバージョンは以下の通りです。
$ bash --version GNU bash, version 3.2.39(1)-release (i486-pc-linux-gnu) Copyright (C) 2007 Free Software Foundation, Inc.



引数の展開例

以下の様に引数を表示するシェルスクリプト(show-args.sh)を用意します。
#!/bin/bash echo "引数の数 : $#" echo "引数 : $@"
このスクリプトに引数 first/here-* を指定して実行すると、 結果として表示される引数の数は幾つになるでしょうか?
$ ./show-args.sh first/here-*



正解は「2」です。
引数の数 : 2 引数 : first/here-is-first1.txt first/here-is-first2.txt
これは、パターンとみなされる文字「*」がパス名展開された結果が、引数となるためです。
(参考: BASH - パス名展開)

文字列として、first/here-*をシェルスクリプトに渡したい場合は、 引数をダブルコーテーションで囲うか、事前にset -fを実行します。
$ ./show-args.sh "first/here-*" 引数の数 : 1 引数 : first/here-* $ set -f && ./show-args.sh first/here-* 引数の数 : 1 引数 : first/here-*



展開のタイミング

展開タイミングによっては展開結果が変わります。
例えば、以下は、here-*が展開されるタイミングによって展開結果が変わる例です。
#!/bin/bash cd first echo "first : " $1 cd ../second echo "second : " $1
./show-args2.sh "here-*" first : here-is-first1.txt here-is-first2.txt second : here-is-second1.txt here-is-second2.txt here-is-second3.txt
ところで、展開が起きるタイミングはいつでしょうか?
私が気になったのは、関数の実行、または変数への代入で展開が起こるのかという点です。


展開のタイミングについて、マニュアルに以下の記載がありました。

BASH - 展開
展開はコマンドラインが単語へ分割された後に (コマンドライン上で) 行われます。

この文章からコマンドの行に含まれる単語をインタプリタ(bash)が識別した後に、 展開が行われることがわかります。
関数は、コマンドと同じように処理されるため、同様に展開が起こるはずです。
以下のシェルスクリプト(show-func-args.sh)で確認してみます。

#!/bin/bash function showFirstArg { echo "引数の数 : $#" echo "引数 : $@" } cd first showFirstArg here-* cd ../second showFirstArg here-*
$ ./show-func-args.sh 引数の数 : 2 引数 : here-is-first1.txt here-is-first2.txt 引数の数 : 3 引数 : here-is-second1.txt here-is-second2.txt here-is-second3.txt
関数の実行で、展開が起こることがわかりました。



では変数への代入はどうでしょうか?
#!/bin/bash cd first VAR=here-* cd ../second echo $VAR
$ ./show-var.sh here-is-second1.txt here-is-second2.txt here-is-second3.txt
変数への代入時に展開が起きているとしたら、firstディレクトリ内のファイルが表示されるはずです。
しかし、secondディレクトリ内のファイルが表示されたことから、変数代入時には展開が起きないことがわかりました。



まとめ

  • 展開によって、引数の数、値が変わる。
  • 展開は、コマンドまたは関数が実行される直前に行われる。
  • 変数への代入では、展開が起きない。

About 2009年4月

2009年4月にブログ「Chronicle it.」に投稿されたすべてのエントリーです。過去のものから新しいものへ順番に並んでいます。

前のアーカイブは2008年6月です。

他にも多くのエントリーがあります。メインページアーカイブページも見てください。