シェルスクリプトサンプルコードでよく見かける typeset や declare ってなに?
後日投稿したエントリで、サンプルコードとともに検証をしてみました。
興味があればそちらも御覧ください。
古いシェルスクリプトコードでは、以下のような命令で変数を定義する方法が取られていることが多いです。
# 定義
$ VAR1=123
# 出力
$ echo "$VAR1"
123
一方、Github で公開されているシェルスクリプトを見ていると、typeset
や declare
を使って変数を定義している例をよく見かけます。
それぞれの違いと使い方について調べてみました。
変数定義の方法は3つ
改めて Bash の変数定義方法を列挙してみます。
Bash では 定義なしに変数を生成 することができるが、 明示的に定義して変数を生成 することもできます。
変数の生成方法は以下の 3 つ。(だと思っている)
VAR1=123
declare VAR1=123
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
の記述でも十分なんですね。
オプション機能がとっても便利そうだがここでは書ききれない
使いこなせるとシェルスクリプトがとても書きやすくなりそうなので、今後のエントリでサンプルコードとともに取り上げていこうと思います。
一旦ここまで。
後日投稿したエントリで、サンプルコードとともに検証をしてみました。
興味があればそちらも御覧ください。
ディスカッション
コメント一覧
> typeset は非推奨となったビルトインコマンドだという記述もありました。(ソースは見失った、、、)
ソースかもしれない候補はこちらです。
– https://stackoverflow.com/questions/4419704/differences-between-declare-typeset-and-local-variable-in-bash
– https://unix.stackexchange.com/questions/66007/what-is-the-difference-between-declare-and-typeset
`typeset` は ksh (や他のシェル)との互換性のために提供されたものですが、少なくとも bash 1.14.7 の時点ですでに非推奨と明記されていました。後にそれが修正され今ではただの別名という扱いである可能性が高いです。
例えば、macOS の デフォルトの bash は 3.2.57 と古くこのバージョンでは
`info bash` で deprecated と
“`
`typeset’
typeset [-afFrxi] [-p] [NAME[=VALUE] …]
The `typeset’ command is supplied for compatibility with the Korn
shell; however, it has been deprecated in favor of the `declare’
builtin command.
“`
`help typeset` で Obsolete と表示されます。
“`
typeset: typeset [-aAfFgilrtux] [-p] name[=value] …
Set variable values and attributes.
Obsolete. See `help declare’.
“`
しかし最新の bash(5.1) ではその表記はなくなっています。コードの変更を追跡した所、bash 4.3 で info が、bash 4.4 で help が修正されています。
https://git.savannah.gnu.org/cgit/bash.git/diff/doc/bashref.info?h=bash-4.3
“`
`typeset’
typeset [-afFgrxilnrtux] [-p] [NAME[=VALUE] …]
The `typeset’ command is supplied for compatibility with the Korn
shell. It is a synonym for the `declare’ builtin command.
“`
https://git.savannah.gnu.org/cgit/bash.git/diff/builtins/declare.def?h=bash-4.4
“`
typeset: typeset [-aAfFgilnrtux] [-p] name[=value] …
Set variable values and attributes.
A synonym for `declare’. See `help declare’.
“`
`help typeset` の修正に関しては以下に記録を見つけましたが、非推奨だった理由については不明です。
– https://lists.gnu.org/archive/html/bug-bash/2016-01/msg00165.html
– https://lists.gnu.org/archive/html/bug-bash/2016-02/msg00145.html
bash においては `declare` が本当の名前で `typeset` が別名という扱いですが、他のシェルとの互換性は `typeset` の方が高いです。
コメントありがとうございます。
**Bash** に限定しないと、 `typeset` キーワードのほうが一般的なんですね。
他シェルで記述することを考慮し、汎用的な `typeset` キーワードを利用したほうが良さそうですね。
勉強になりました。