シェルスクリプトサンプルコードでよく見かける typeset や declare ってなに?
後日投稿したエントリで、サンプルコードとともに検証をしてみました。
興味があればそちらも御覧ください。
古いシェルスクリプトコードでは、以下のような命令で変数を定義する方法が取られていることが多いです。
一方、Github で公開されているシェルスクリプトを見ていると、typeset
や declare
を使って変数を定義している例をよく見かけます。
それぞれの違いと使い方について調べてみました。
変数定義の方法は3つ
改めて Bash の変数定義方法を列挙してみます。
Bash では 定義なしに変数を生成 することができるが、 明示的に定義して変数を生成 することもできます。
変数の生成方法は以下の 3 つ。(だと思っている)
VAR1=123
declare VAR1=123
typeset VAR1=123
それぞれの違いは何?便利な機能もありそうなので調べてみました。
1. declare
/ typeset
なしの変数定義
最もよく見る変数定義方法。
記述もシンプルで流れるようにコーディングしているときにはよく記述します。
2. declare
を使った変数定義
一緒に見えますね。
3. typeset
を使った変数定義
これも一緒!?
困ったので man
ページを見る!
declare
/ typeset
コマンドとは
こちら Bash のビルトインコマンドのようですね。
man
コマンドで bash
のマニュアルをのそいてみます。
と表示され、答えは一目瞭然。両者に違いはありません。
ただ、 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` キーワードを利用したほうが良さそうですね。
勉強になりました。