みなさま毎度お疲れ様です。
Numataです。
今回は、シェルを書いていて、少し苦戦した話を備忘録としてまとめます。
シェルは開発コーディングのように、変数の中に変数入れて文字列と結合して、、、
といった複雑な使い方するには向いていないんだろうな。。
(そもそもそういった意図で作られていないハズ)
と感じた出来事でした。
それではいってみましょう。
もくじ
シェルにおける変数とは
シェルには変数という概念が存在します。
プログラミングでよく言われる変数の概念は”箱””入れ物”です。
変数宣言して中に値を代入して。。という一番最初に学習するヤツです。
(今回は変数の説明は省きます。)
シェルの変数宣言の方法はどシンプルです
1 2 |
#シェルの変数宣言 hensu=atai |
以上です。そのまますぎて逆に違和感満載です。
左辺に辺数名、右辺に入れたい値を入れます。
”=”の両脇にスペース” ”を入れてはいけないことに注意!
これでhensuという変数に、ataiという文字列が入ります。
では、宣言した変数を呼び出して、中の値を出力してみましょう。
変数の呼び出し方法は2種類あります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
#シェルでの変数呼び出し #echoで出力 #パターン1 echo $hensu #出力 atai #パターン2 echo ${hensu} #出力 atai |
宣言した変数の前に”$”をつけると、文字列が変数として扱われるというわけです。
パターン1では、$をつけただけ、
パターン2では、$プラス{}がついています。
どちらも正解で、正しく動くのですが、圧倒的に
パターン2の方が見やすいですよね。
パターン1、パターン2が同リソースの中で混在していることも
少なくありません。
可読性の面を鑑みても、パターン2の書き方をオススメします。
動的な変数を作りたい
今回の主題はこれです。
シェルにおいて、動的な変数を作るにはどうするのが
スマートな方法なのでしょうか。
これに2時間弱つまづいたので、整理しておきます。
まず、今回作りたかった変数は以下のようなものです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
#変数にファイル名を設定 file_1="fl001" file_2="fl002" file_3="fl003" file_4="fl004" #シェルの中でファイルの番号が設定される file_number=2 #設定されたファイル番号のファイルを呼び出したい(これだとエラー) echo file_$file_number #出力 file_2 |
ここで出力したいのは”fl002”なのですが、
”file_2”が出力されてしまいます。
echoコマンドの後に、変数の印である$を入れてないからですね。
では$を入れたらどうなるでしょう。
1 2 3 4 5 |
#$を入れると。。 echo $file_$file_number #出力 2 |
はい、2が出力されてしまいます。
理由は、”file_”という変数が存在していないからです。
シェルでは、文字列結合に”+”などの演算子が必要ありません。
変数名を続けて書くだけで勝手に連結されます。
これが仇となり、変数$file_ と 変数$file_number が結合し、
2となるわけです。(存在しない変数は無視されます。)
といった具合で、出力したい変数名を動的に作り出すことが
一筋縄ではいきません。。
解決策はたくさんあると思いますが、
今回は2パターンで考えてみたいと思います!
動的な変数の解決策
①evalコマンドを使う
evalコマンドとは、こんなことができるコマンドです。
指定した文字列を評価後に連結して、現在のシェルに実行させます。
引用元:https://www.atmarkit.co.jp/ait/articles/1712/22/news019.html
文字列を評価してくれるというところがポイントです。
”評価”ということは、与えられた文字列を、
文字列or変数で、判断して使ってくれるということです。
このevalコマンドを上手に使って、動的な変数を作ることができます!
1 2 3 4 5 6 |
#evalを使った動的変数の作り方 eval echo '$'$"file_"${file_number} #出力 fl002 |
ただ。。
このソース読みづらいですよね(笑)
シンプルだし一発で変換できる点は良いですが、
可読性に欠けるかもしれません。
(特にコマンドをよく知らない人はなんのことか。。)
私は、シェルほとんど初心者なのですが、
最初にこのソース見たら何しているかわからなかったかもしれません!
②if文で分岐作る
少し長くなりますが、
if文で分岐作ると、ぱっと見で見やすいソースになります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
#if文で、file_numberの中身に応じて分岐を作る if [ ${file_number} -eq 1 ]; then echo ${file_1} fi if [ ${file_number} -eq 2 ]; then echo ${file_2} fi if [ ${file_number} -eq 3 ]; then echo ${file_3} fi if [ ${file_number} -eq 4 ]; then echo ${file_4} fi |
こちらのソースだと、パッと見ただけで何しているかわかりますね。
動的変数は初心者が簡単にできるものではなかった。。!
私は、そもそもがシェルをほとんど触ったことがなく、
ネットで知ったコマンドをその場その場で組み合わせて
ソースを読んだり書いたりしていました。
しかし、今回のようなケースにあたり、
エラーの解決に2時間弱もかかってしまいました。
初学者だと、
evalコマンドも知らないし、そもそもどうやって文字列結合されるかも知らないし、変数呼び出しの方法に種類があることも知らないし、、、
とわからないことだらけで混乱してしまいます。
今回改めて思いましたが、一歩一歩解決していくことがエラー解決の鍵ですね。。
ご参考になれば!!
コメント