シェルスクリプトサンプルコードでよく見かける typeset や declare ってなに?

2022-03-08Bash,Cygwin,Linux,Ubuntu

後日投稿したエントリで、サンプルコードとともに検証をしてみました。
興味があればそちらも御覧ください。


古いシェルスクリプトコードでは、以下のような命令で変数を定義する方法が取られていることが多いです。

# 定義
$ VAR1=123

# 出力
$ echo "$VAR1"
123

一方、Github で公開されているシェルスクリプトを見ていると、
typesetdeclare を使って変数を定義している例をよく見かけます。

それぞれの違いと使い方について調べてみました。

変数定義の方法は3つ

改めて Bash の変数定義方法を列挙してみます。

Bash では 定義なしに変数を生成 することができるが、 明示的に定義して変数を生成 することもできます。
変数の生成方法は以下の 3 つ。(だと思っている)

  1. VAR1=123
  2. declare VAR1=123
  3. typeset VAR1=123

それぞれの違いは何?便利な機能もありそうなので調べてみました。

1. declare / typeset なしの変数定義

最もよく見る変数定義方法。
記述もシンプルで流れるようにコーディングしているときにはよく記述します。

$ X=hello

$ echo "$X"
hello

2. declare を使った変数定義

$ declare X=hello

$ echo "$X"
hello

一緒に見えますね。

3. typeset を使った変数定義

$ typeset X=hello

$ echo "$X"
hello

これも一緒!?
困ったので man ページを見る!

declare / typeset コマンドとは

こちら Bash のビルトインコマンドのようですね。

$ type declare
declare is a shell builtin

$ type typeset
typeset is a shell builtin

man コマンドで bash のマニュアルをのそいてみます。

$ man bash
...(一部省略)...
       declare [-aAfFgilnrtux] [-p] [name[=value] ...]
       typeset [-aAfFgilnrtux] [-p] [name[=value] ...]
              Declare  variables  and/or give them attributes.  If no names are given then
              display the values of variables.  The -p option will display the  attributes
              and  values  of  each name.  When -p is used with name arguments, additional
              options, other than -f and -F, are ignored.  When  -p  is  supplied  without
              name  arguments,  it will display the attributes and values of all variables
              having the attributes specified by the  additional  options.   If  no  other
              options are supplied with -p, declare will display the attributes and values
              of all shell variables.  The -f option will restrict the  display  to  shell
              functions.  The -F option inhibits the display of function definitions; only
              the function name and attributes are printed.  If the extdebug shell  option
              is enabled using shopt, the source file name and line number where each name
              is defined are displayed as well.  The -F option implies -f.  The -g  option
              forces  variables  to  be created or modified at the global scope, even when
              declare is executed in a shell function.  It is ignored in all other  cases.
              The  following  options can be used to restrict output to variables with the
              specified attribute or to give variables attributes:
...(一部省略)...

と表示され、答えは一目瞭然。両者に違いはありません。

ただ、 Shell Style Guide のサイトを調べてみると、 declare 命令に関する記述はいくつか見つかりますが、 typeset に関する記述が皆無なので、 declare を使うのが良さそう。別のサイトには、 typeset は非推奨となったビルトインコマンドだという記述もありました。(ソースは見失った、、、)

declare コマンドのオプション

オプションが多数あります。

オプションを指定して変数の定義時に型を指定できます。
その他、プリントデバッグ(変数の型や中身を確認)できたり、読み取り専用にしたり、大文字、小文字への変換を強制したりなど、変わった機能もあります。

オプションと機能の概要をざっと列挙してみます。

オプション機能の概要
-A連想配列として変数を定義
-a配列として変数を定義
-i整数として変数を定義。 = の右辺を数式として認識し評価結果を代入。
-l大文字を自動的に小文字に変換する変数 を定義
-u小文字を自動的に大文字に変換する変数 を定義
---------------------------------------------------------------------------------
-r読込専用な変数を定義。値を代入したり unset したりできなくなる。
---------------------------------------------------------------------------------
-x変数をエクスポート。 export と同義
-f定義されている関数名を出力
-p定義されている変数を出力(プリントデバッグ)

オプション無しの変数定義はみんな一緒!

オプションを指定して初めて declare 命令が生きてきます。
オプション無しでは VAR1=123 の記述でも十分なんですね。

オプション機能がとっても便利そうだがここでは書ききれない

使いこなせるとシェルスクリプトがとても書きやすくなりそうなので、今後のエントリでサンプルコードとともに取り上げていこうと思います。

一旦ここまで。


後日投稿したエントリで、サンプルコードとともに検証をしてみました。
興味があればそちらも御覧ください。

2022-03-08Bash,Cygwin,Linux,Ubuntu