積雲が映像制作したMV『RANGEFINDER』公開中
専門88IO

シェルスクリプトの楽しみ方入門【ひっかかり編】

専門

Manjaro Linux Awesome WM Edition 2019標準の.zshrcは完成されています。(主観)

  1. 強力な補完機能
  2. コマンドのハイライト
  3. ディレクトリの省略
  4. Gitのステータス表示

などの機能も標準で揃っています。おすすめなので是非導入を!(布教)

 

導入はこれくらいにして本題に移ります。また、今回はBash Scriptをシェルスクリプトを解釈して進めていきます。

スポンサーリンク

シェルスクリプトは繊細

変数定義の半角スペース

C++やRustなど僕が今まで触ってきたプログラミング言語で変数を定義する場合、

// C++
int num = 8810;
// Rust
let mut num: u32 = 8810;

と定義していました。イコール(=)の間に半角スペースを空けることで可読性を向上させているのですが、空けなくても問題ないです。

しかし、シェルスクリプトでは以下のコードはエラーになります。

# Err
num = 8810

変数名と値の間に空白を入れてはいけないです。正しくはこちら。

# Ok
num=8810

また、文字列はクォーテーション(’)やダブルクォーテーション(”)で囲うのが一般的(だと思っている)ですが、シェルスクリプトにこの規約はありません。以下のコードは問題なく動作します。

greet=hello
echo $greet # -> hello

$var と ${var }

先程、$greetというコードを書きました。変数を呼び出すときは変数の頭に$をつけます。

入門サイトを見て回ると${greet}のように表記してある場合もあり、あまり理解せずに「動くから。」と気にしない人もいます。(入門している友人でそのケースに出くわした。)

実際、どちらでもいいです。ただ、変数名が明確であるという点で後者への統一がおすすめです。

greet=hello

# hello_worldと表示させたい
echo $greet_hello  # -> ?
echo ${greet}_hello  # -> ?

前者は$greet_worldと書いたときにgreet_worldという変数として解釈されるために見つからず、文字は出力されません。対して、${greet}_worldと記述することでgreetという変数名であると認識されるため、”hello_world”ときちんと表示されます。

シェルスクリプトでは定義されていない変数を用いると、”undefined”とエラーが発生するわけでもなく、長さ0の文字(?)として扱われます。そのため、”定義されているか”という条件分岐を行うことができますが、エラーが発生しないため原因追及が難しいです。

また、シェルスクリプトでの文字列は足し合わせるのではなく、変数部分を置き換えるといったイメージであるのが特徴的です。感覚的につかめればOKです。

条件分岐 if [ ]; then … fi

変数aの値が0であるか判定したい場合、if (a == 0) と書くイメージがありませんか。シェルスクリプトはこのイメージからかけ離れた表記をします。以下は変数a(既に整数で定義済)の値が0であるか判定し、0であれば 文字の出力を行うプログラムです。

if [ $a -eq 0 ]; then
    echo "a equals to zero."
fi

fiはおそらくFinの略です。-eqequals toを示し、”a equals to 0″(a == 0)であるかを判断します。

他にも、

0より大きいa is greater than 0$a -gt 0
0と等しいa equals to 0$a -eq 0
0より小さいa is less than 0$a -lt 0

といった表記ができます。頭文字から取っていることが分かります。英文で覚えた方がいいと思います。

では、”0以上”はどのように表記するか。英文で”a is greater than or equals to”なので-geですね。他も同様です。

また、シェルスクリプトの条件分岐に関してもう一つ気をつけなければならない箇所があります。

それは[ ]内の半角スペースです。

[$a -eq 0]と書くとエラーが発生します。カッコ内両端は必ず半角スペースで空ける([ $a -eq 0 ])必要があります。なんだか変数定義のときとは逆ですね。

>> /dev/null

シェルスクリプトはLinux(UNIX)コマンドの資産を容易に活用することができます。コマンドを``で囲うとその部分がコマンド実行時の出力に置き換わります。一応、サンプルコードを載せておきます。

list=`ls ./`

echo $list  # -> Desktop Documents ...

この場合、lsコマンドによる出力が変数listに格納されます。

しかし、純粋にコマンドを実行した場合はどうなるでしょうか。

ls ./
# -> Desktop Documents ...

こちらも指定ディレクトリ内のファイル一覧が出力されたと思います。

ここで、”コマンドの実行はしたいが出力はしたくない”としましょう。やっと>> /dev/nullの出番です。

ls ./ >> /dev/null
# ->
>>は標準出力を表示する代わりにファイルに書き込む機能です。今回はlsコマンドによる出力を/dev/nullに書き込んでいます。(/dev/nullはゴミ箱と思っていただいて構わないと思います。つまり出力を捨てているのです。)

ちなみにVimでReadOnlyのファイルを編集した後に書き込みを行うときにも使いました。

:w !sudo tee % >> /dev/null

適当に書いてみましたが、どうでした?

この手のネタは書きやすいので楽です。次のシェルスクリプトに関する記事では、”実際に僕が.zshrcで行ったカスタマイズ”、”友人がやりたかったこと・ミスっていたこと”を書く予定です。

【初心者あるある編】【zshカスタマイズ編】に続く!(未定)

コメント

タイトルとURLをコピーしました