LoginSignup
0
3

More than 1 year has passed since last update.

シェルスクリプトの基本的な文法と演習

Posted at

はじめに

シェルスクリプトにまつわる記事を投稿し始めて、早くも3本目。これまでは実際に.shファイルを作成するまでの基礎的な部分を説明してきたため、実際にファイルを作って動かしてみることはやってきませんでした。
 しかし改めて.shファイルを記述して、エラーを出して、なんとか動かしてみるとやっぱりこれが一番楽しいですね。エンジニアになって良かった。地球に生まれて良かったとすら思えます。
前回までの記事:

 具体的に行った手順をメモにして残して、読んでいただけた方には実際に手を動かしてシェルスクリプトを書いて欲しいですね。それが上達にもつながる気がしています。
 通して読んでくださっている方には本当に感謝です。それでは文法から、見ていきましょう!

シェルスクリプトの基本

 シェルスクリプトは独特の文法構造を持っており、やはり書いていかないことには身につかないと思います。(変数の定義にスペースを使わない。全角スペースが入っていても空行は無視される。等)
基本的な文法を下記のようにまとめておくので、ぜひ手を動かして書いてみて欲しいです。
全て私が実践して、実際に動いたスクリプトを掲載しています。動かせる環境を作れることも重要なのでご自身でやってみてください。それでは行きましょう。

シェルスクリプトの行

・\で改行できる。(\はoption+¥キーで入力できる)

dinner.sh
#!/bin/bash -eu

echo \ (変なところで改行している。)
"Today's dinner."
mbp:shellscripts kentaroyoshizumi$ . dinner.sh (カレントディレクトリでdinner.shを実行せよという意味)
Today's dinner.

コメント

**・#の直後はコメントになる。

dinner.sh
#!/bin/bash -eu

echo \
"Today's dinner."  #today is my birthday.

変数

シェルスクリプトで使用する変数を「シェル変数」と呼ぶ。シェル変数を定義するには、変数名の前に「$」をつける。
ただし注意もあり、

  • 変数を定義する際に$をつけてしまうとエラーになる。
  • 変数を定義する際に=の前後にスペースを入れてしまうとエラーになる。(birthday = 1021 等)
  • 変数名に利用できるのはアルファベットと数字と_のみ。
  • 変数名に_を使用する際には{}で括らなければならない。(後述)
birthday.sh
#!/bin/bash -eu

bitrthday=1021
echo $birthday

実行結果

mbp:shellscripts kentaroyoshizumi$ . birthday.sh
1021

変数名に_を使用する際には{}で括らなければならない。

birthday1.sh
#!/bin/bash -eu

bitrthday=1021
echo $birthday_today_is_my_birthday

実行結果

mbp:shellscripts kentaroyoshizumi$ . birthday.sh
(何も表示されない)
birthday1.sh
#!/bin/bash -eu

bitrthday=1021
echo ${birthday}_todayismybirthday

実行結果

mbp:shellscripts kentaroyoshizumi$ . birthday.sh
1021_todayismybirthday

クォーティング

シングルクォートとダブルクォートで実行結果が異なる。

quote.sh
#!/bin/bash -eu
country=Japan
echo 'I came from $country'
echo "I came from $country"

実行結果

I came from $country
I came from Japan

コマンド置換

コマンドの結果を文字列として取得する。

date.sh
#!/bin/bash -eu

filename=$(date '+%Y-%m-%d')
echo "$filename"

実行結果

2022-03-27

位置パラメータ

めっちゃ使います!

$ echo $?
0

直前に使用したコマンドがうまく行ったかどうかを示す。(0なら成功、1は失敗)

位置パラメータのテスト用シェルスクリプト

param.sh
#!/bin/bash -eu

echo "\$0 = $0"
echo "\$1 = $1"
echo "\$2 = $2"
echo "\$3 = $3"

コマンドラインから以下を実行

$ ./param.sh aaa ggg ttt

出力結果

$0 = ./param.sh
$1 = aaa
$2 = ggg
$3 = ttt

制御構造

bashは他のプログラミング言語同様条件分岐や繰り返し処理を行うことができる。

if文

if-bin.sh
#!/bin/bash -eu
if [ "$1" = "bin" ]; then
 echo "OK"
else
 echo "NG"
fi

for文

単語のリストに対して繰り返し処理を行う

forexample.sh
#!/bin/bash -eu

for name in aaa ccc ggg
do
 echo $name
done

実行結果

aaa
ccc
ggg

case文

指定された文字列がパターンにマッチするか判定し、パターンごとに対応した処理を行う。

case-test.sh
#!/bin/bash -eu

case "$1" in
*.txt)
less "$1"
;;
*.sh)
vim "$1"
;;
*)
echo "not supported file : $1"
;;
esac

実行結果

mbp:shellscripts kentaroyoshizumi$ . case-test.sh /Users/kentaroyoshizumi/Downloads/RubyProject
not supported file : /Users/kentaroyoshizumi/Downloads/RubyProject

while文

指定した条件が真である限りくりかえし処理を行う。

while.sh
#!/bin/bash -eu

i=1
while [ "$i" -le 10 ]
do
 echo "$i"
 i=$((i + 2))
done

実行結果

mbp:shellscripts kentaroyoshizumi$ . while.sh
1
3
5
7
9

シェル関数

シェルスクリプト内で関数を定義する

func-test.sh
#!/bin/bash -eu

horizonte ()
{
date
du -h ~| tail -n 1
}

horizonte

実行結果

mbp:shellscripts kentaroyoshizumi$ . func-test.sh
2022年 4月 2日 土曜日 16時58分49秒 JST

シェル関数内での位置パラメータ

シェルスクリプトの中で位置パラメータを使用する。

func-parameter.sh
#!/bin/bash -eu

echo_parameter ()
{
 echo "\$1 = $1"
 echo "\$2 = $2"
 echo "\$3 = $3"
 echo
 echo "$# arguments"
 echo "scripts name= $0"
}

echo_parameter aaa bbb ccc

シェルスクリプトの活用

演習1-1 指定されたファイルやディレクトリの概要を表示するシェルスクリプト

summarize.sh
#!/bin/bash -eu

file=$1

if [ -d "$file" ]; then
  echo "$file is a directory:"
  ls "$file"
elif [ -f "$file" ]; then
  echo "$file is a regular file:"
  head -n 5 "$file"
fi

実行結果

shellscripts is a directory:
birthday.sh	date.sh		if-bin.sh	summarize.sh
daily.sh	dinner.sh	param.sh

演習1-2 前問の複数ファイルを指定したもの

summarize1.sh
#!/bin/bash -eu

for file in "$@"
do
  if [ -d "$file" ]; then
    echo "$file is a directory:"
    ls "$file"
  elif [ -f "$file" ]; then
    echo "$file is a regular file:"
    head -n 5 "$file"
  fi
done

実行結果

RubyProject is a directory:
2:15_S3_or_not.drawio		hello_ruby
2:15_S3_or_not.png		mail
Yoshizumi_new.drawio		monitoring_solution.png
Yoshizumi_solution13.drawio	my-portfolio-site.drawio
Yoshizumi_solution13.png	my-portfolio-site.png
Yoshizumi_solution14.png	new.drawio
batch_sample			ninjacode
business-idea.drawio		rails-hotel-search-linebot
business_idea.drawio		rails-lecture
business_idea.png		rails-react-auth
docker-compose1.yml		renew_datamonitoring.drawio
docker-practice			renew_datamonitoring.png
hello.rb			ruby-lecture

演習2 日記を書くスクリプト

①daily.shというファイルを作成して、vimで編集していく。

daily.sh
mbp:shellscripts kentaroyoshizumi$ touch daily.sh
mbp:shellscripts kentaroyoshizumi$ vim daily.sh
#!/bin/bash    #(シバンを指定する。今回はやはりbash)

#日記データを保存するディレクトリ
directory="${HOME}/shellscripts"

#保存するディレクトリがなければ作る
if [ ! -d "$directory" ]; then
 mkdir "$directory"
fi

vim "${directory}/$(date '+%Y-%m-%d').txt"    #(shellscripsというディレクトリに日付.txtという名前で保存した後vimで編集する。)

演習3 指定したパスのファイル一覧

open.sh
#!/bin/bash -eu

list_recursive ()
{
 local filepath=$1
 local indent=$2

 echo "${indent}${filepath##*/}"

 if [ -d "$filepath" ]; then

 local fname
 for fname in $(ls "$filepath")
 do
   list_recursive "${filepath}/$
{fname}" "  $indent"
 
 done
fi
}

list_recursive "$1" ""
0
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
3