Posted at

Linux初心者のシェルスクリプト入門

More than 3 years have passed since last update.


はじめに

情報系の大学生や社会人なら触れる機会も多いであろうlinux

そしてlinuxで作業する上で欠かせないのが、数多くのコマンド類

しかし、コマンドだけではとてもじゃないがやっていられない作業もある

そんな時に使えると便利なのがシェルスクリプトと言われるもの

これは複数のコマンドを一つのファイルにまとめ、一気に実行できるようにするためのものである

linuxを使い始め、コマンドがある程度使えるようになったのなら是非とも習得してみたいものだ

この投稿内では、ShellScriptを記述する上で必要最低限の情報をまとめていく

なので、上から順に見ていくのもよし、困った時にチートシート代わりに使用するのもいいだろう

それでは早速始めていく


シェルスクリプトで「Hello,World!!」

プログラミング入門時に定番の「Hello,World!!」の出力をシェルスクリプトでもやってみる

シェルスクリプトではlinuxコマンドであるのもは使えるので、出力をechoコマンドで行うことができる

またコマンド単体で実行することもできる

そして以下のコードを「hello.sh」というファイル名で作成する


hello.sh

#!/bin/sh

echo "Hello,World!!"


作成したら以下のコマンドでパーミッションを実行可能にする

$ chmod u+x hello.sh

パーミッションを実行可能にしたらシェルスクリプトを実行させる

$ ./hello.sh

これで簡単なシェルスクリプトを書いて、実行させることができた

またhello.shの一行目に書いてある「#!/bin/sh」という記述はシェルスクリプトを書く上で必要なものでシェルshのパスを表しる

またbashの独自機能を利用したい場合は「#!/bin/bash」となる。

加えて、シェルスクリプトでは文字列を””でくくる必要は無いのでhello.shは以下のようにも書ける

#!/bin/sh

echo Hello,World!!


変数

シェルスクリプトにはプログラミング言語と同じように変数を宣言、定義できる

またシェルスクリプトの変数はpythonの変数にすごく近い


シェル変数

シェルスクリプト内での変数をシェル変数といい、"="で利用できる


sample.sh


#!/bin/sh

val1="Hello,World!!"
val2=20

echo val1
echo "age:${val2}"


上記がシェル変数を利用したコードの例である

変数の利用は=で行い、文字列と変数を繋げたい場合は「${変数名}」で連結できる


引数

変数と関連して、他のコマンドと同様にシェルスクリプトにも引数を渡すことができる

その引数の扱い方を紹介する


catn.sh

#!/bin/sh

cat -n $1


上記の例であるように、n番目の引数を呼び出すには「$n」とする

また引数の順番について具体例を上げると

$ ./catn.sh sample.sh

| $0 | | $1 |

となる。つまり$0はシェルスクリプト名になりその後は順に数値が増えていく

このように引数を扱えるものなどを特殊変数という

特殊変数は以下のものが使用可能

特殊変数
意味

$0
シェルスクリプトの名前

$n
n番目の引数

$*
すべての引数リスト

$#
与えられた引数の数

$?
直前に実行したコマンドの戻り値

$$
シェルスクリプトが実行された際のPID

$LINENO
この変数を記述した行番号


条件分岐

ここではシェルスクリプト内部で条件判定によって処理を切り替える方法をまとめる


if

シェルスクリプトで条件分岐を行うときはif文を使用する


sample_if.sh

#!/bin/sh

if [ $1 = hello ]
then
echo arg is hello
elif [ $1 = world ]
then
echo arg is world
else
echo arg is neither hello nor world
fi


上記の例で示したように、if文は[]内に条件を入れthenをつける

また複数の条件を扱うときはelifでつなぎif同様thenでつなぐ、elseはそのまま使用し

条件分岐の終わりはfiで閉じる


test

実はif文において条件判定に[]ではなく真偽を判定するtestコマンドを使用することも出来る

その場合は以下のようになります


sample_test.sh

#!/bin/sh

if test -f $1; then
echo File $1 exists
fi


今回はコマンドを使用しているため;で区切ってthenを入れています

これらのオプションについては後述


case

これはもうほぼほぼswitch~case文で以下のように記述します


sample_case.sh

#!/bin/sh

case $1 in
hello) echo hello ;;
world) echo world ;;
*) echo other ;;
esac


まずcaseの後に判定したい変数などを指定し、その後に「条件)」といった形で判定していく

*)は多くのプログラミング言語におけるswitch~case文のdefaultにあたる

また末尾に;;を忘れないこと


testコマンド オプションチートシート


- 文字列

オプション
意味

-n string

文字列の長さが0でないなら真

-z string

文字列の長さが0なら真

string1 = string2

同一なら真

string1 != string2

同一でないなら真


- 数値

オプション
意味

num1 -eq num2

等しいなら真

num1 -ne num2

等しくないなら真

num1 -gt num2

num1がnum2より大きいなら真

num1 -ge num2

num1がnum2以上なら真

num1 -lt num2

num1がnum2より小さいなら真

num1 -le num2

num1がnum2以下なら真


- ファイル

オプション
意味

-f file

fileが存在し、通常ファイルなら真

-c file

fileが存在し、キャラクタスペシャルファイルなら真

-e file

fileが存在すれば種類によらず真

-d file

fileが存在し、ディレクトリなら真

-L file

fileが存在し、シンボリックなら真

-r file

fileが存在し、読み取り可能なら真

-w file

fileが存在し、書き込み可能なら真

-x file

fileが存在し、実行可能なら真


- 複合式

オプション
意味

expr1 -a expr2

2つの式の論理積をとる

expr1 -o expr2

2つの式の論理和をとる

!expr

式の否定を返す


ループ

シェルスクリプトにもループは存在し、これはpythonとよく似ている


for

単純にループを使いたいなら、forを使う


sample_for.sh

#!/bin/sh

for str in hello world shell; do
echo $str
done


上記の例のようにfor文は「for 変数名 in 文字列1 文字列2 .... ; do ~ done」と記述することで実現できる


seq

for文を使うなら覚えておきたいseqコマンドというものがある

これはpythonでのrange関数に相当し、seq 第一引数 第二引数と記述することで

第一引数以上第二引数以下の整数を順番にループしてくれるというもの

なのでこれを用いてfor文を使うと以下のようになる

#!/bin/sh

for number in `seq 1 3`; do
echo "${number}"
done

このコードでは1,2,3とループされる

またseqコマンドを囲んでいるのが「''(シングルクォート)」ではなく「``(バッククォート)」であることに注意


while,expr

for文は一定の回数ループ処理を行いたいときに使用したが、回数不明の時にはwhile文を使用する

また説明の都合上exprコマンドが唐突に登場するがこれは後述

とりあえず、回数がわかりにくい例としてフィボナッチ数列を実装してみる


sample_while.sh


#!/bin/sh

max=40
a=1
b=1

while [ $b -le $max ]; do
echo $b

a=`expr $a + $b`
b=`expr $a - $b`

done


このシェルスクリプトでは変数max以下のフィボナッチ数列を計算している

このように回数がわからないがループ処理をしたいときにはwhile文が有効


- expr

while文の時に唐突に登場したこのコマンドは上記の例を見てくれればわかると思うが

「expr num1 演算子 num2

とすればnum1とnum2に演算を適用し、その結果を返してくれるもの


関数を使用する

シェルスクリプトでは関数をサポートしていて、いくつかの処理を一つの関数としてまとめることができる

#!/bin/sh

func(){
echo $1 + $2 = `expr $1 + $2`
}

x=10
y=2

func $x $y

上記の例でわかるように「関数名(){ 処理 }」という形で関数は実現され

シェルスクリプトに引数を渡すように関数にも渡すことができる