15
19

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

【Linux】シェルスクリプトについて学んだことを書く

Last updated at Posted at 2019-10-04

はじめに

シェルスクリプトについて、学んだことを備忘録としてまとめる。

shにするかbashにするか

  • shの特徴
    • 長い歴史を持つ反面,現在では設計が古い
    • 過去のシェルスクリプトの多くがsh向けに書かれている
    • Debian系ディストリビューションではshをdashとシェルで実装
    • Red Hat系ディストリビューションはshをbashの別名として実装(shとbashに実体はRed Hat系では同じ)
  • bashの特徴
    • shよりもシェルスクリプトを書く上で便利な機能が用意されている
    • 現代のLinuxでは,bashはほぼデフォルトでインストールされている

shよりもbashを検討したほうがいい

理由

  • シェルスクリプトの互換性・移植性が高い

    →shはすべてのLinuxに存在するが,OSによって実装の差異がある

  • 便利な機能が用意されている

→算術計算する際,shでは外部コマンドexprを使用する必要があるが,bashで外部コマンドなしに計算可能(シェル内部の機能なため,動作も高速)

シェルスクリプトの実行形

ファイルの先頭に#!で始まる行を追加する必要があるが,これは**shebang(シバン,シェバン)**と呼ばれるもの.
Linuxカーネルが#!を確認すると,その後ろのコマンドを実行する.
#!/bin/bashは「このシェルスクリプトは/bin/bashで動かす」という意味.
シバンを書くことにより,/bin/bashをコマンドラインに書かなくても,ファイル名を指定することにより,シェルスクリプトを実行できる

alias_set.sh
#!/bin/bash
alias lsalf='ls -alf'

$ lsalf #エイリアス未設定
lsalf: コマンドが見つかりません

$ source ./alias_set.sh #sourceコマンドでエイリアス設定
$ lsalf
arg.sh         if-bin.sh  getdate.sh    homesize.sh  tes1.sh  .
parameters.sh  rootls.sh  alias_set.sh  2019-10-02   ..

$ lsalfsh #エイリアスは未設定
lsalfsh: コマンドが見つかりません
$ cat alias_set.sh  #lsalfの名前をlsalfshに変更後,catで内容表示
#!/bin/bash
alias lsalfsh='ls -lf' #lsalfshに変更

$ ./alias_set.sh #シェルスクリプトを実行
$ lsalfsh        #シェルスクリプト終了後もエイリアスは未設定
lsalfsh: コマンドが見つかりません

これはなぜ起こるのか.
まずsourceコマンドでは,カレントシェルでシェルスクリプトが実行されるため,現在の環境が引き継がれる.
それに対し,ファイル名で実行した場合には,サブシェルでシェルスクリプトが実行されるため,元のシェルとは別物であり,エイリアスの設定は引き継がれない.(環境変数は引き継がれる)
サブシェルとは,現在のシェルから新しく起動される子プロセスのシェルのこと.

$ ./rootls.sh 
root directory
合計 483908
drwxr-xr-x   2 root root      4096  9月 30 11:54 bin
drwxr-xr-x   3 root root      4096  9月 30 11:56 boot
drwxrwxr-x   2 root root      4096  9月 30 00:24 cdrom
drwxr-xr-x  18 root root      4020  9月 30 21:54 dev
略

変数名の参照

変数の値を参照するには,変数名の前に$を付ける
変数の書き方の注意

  • 代入時には$を付けない
  • =の前後にはスペースを入れない
  • 変数名に利用できる文字はアルファベットと数値とアンスコのみ
  • {}を使用して変数名の区切りを明示する
  • ex) 変数名(filename)+任意の文字列(str)を連結して標準出力する場合
    • ダメな例⇒echo filename_str
    • 正しい例⇒echo {filename}_str

クウォーティング

クウォーティングで囲まれた文字列は一つの単語として認識される
''""の違いについて
変数展開が有効かどうか
シングルクォート:$による変数の展開が行われない
ダブルクォート:$による変数の展開が行われる

コマンド置換

getdate.sh
#!/bin/bash

filename=$(date '+%Y-%m-%d')
touch "$filename"
$ ./getdate.sh
$ ls -l
合計 16
-rw-r--r-- 1 gyokoyama gyokoyama  0 10月  2 08:00 2019-10-02
-rwxr-xr-x 1 gyokoyama gyokoyama 60 10月  2 07:59 getdate.sh
-rwxr-xr-x 1 gyokoyama gyokoyama 32 10月  1 08:03 homesize.sh
-rwxr-xr-x 1 gyokoyama gyokoyama 50 10月  1 09:01 rootls.sh
-rwxr-xr-x 1 gyokoyama gyokoyama 20 10月  1 08:15 tes1.sh

2019-10-02というファイル名が追加されている.

位置パラメータ

parameters.sh
#!/bin/bash

echo "\$0 = $0"
echo "\$1 = $1"
echo "\$2 = $2"
echo "\$3 = $3"
echo "\$4 = $4"
echo "\$5 = $5"
$ ./parameters.sh aaa bb ccccc
$0 = ./parameters.sh
$1 = aaa
$2 = bb
$3 = ccccc
$4 = 
$5 = 

ワイルドカードの使用

*:任意の文字列の代わりになる.文字列の長さは0でもよい.
?:任意の1文字の代わりになる.
[]:かぎ括弧の中に記述した任意の1文字の代わりになる。連続する文字コードの指定には - 記号が使える。たとえば, [a-c] は [abc] と同じ意味.

$ ls
2019-10-02  getdate.sh  homesize.sh  parameters.sh  rootls.sh  tes1.sh
$ ./parameters.sh *
$0 = ./parameters.sh
$1 = 2019-10-02
$2 = getdate.sh
$3 = homesize.sh
$4 = parameters.sh
$5 = rootls.sh

引数の個数

コマンドライン引数に指定された引数の個数は$#という変数で参照できる.
最後の行にecho "\$# = $#"を追記.

paraters.sh
#!/bin/bash

echo "\$0 = $0"
echo "\$1 = $1"
echo "\$2 = $2"
echo "\$3 = $3"
echo "\$4 = $4"
echo "\$5 = $5"
echo "\$# = $#"
$ ./parameters.sh *
$0 = ./parameters.sh
$1 = 2019-10-02
$2 = getdate.sh
$3 = homesize.sh
$4 = parameters.sh
$5 = rootls.sh
$# = 6
$./parameters.sh aaa bb c
$0 = ./parameters.sh
$1 = aaa
$2 = bb
$3 = c
$4 = 
$5 = 
$# = 3

引数全体の参照

$@$*を使用して,引数を分割せず全て一括りのようにして参照する.

arg.sh
#!/bin/bash

echo "\$@ = $@"
echo "\$* = $*"
$ ./arg.sh aa bbbb cc
$@ = aa bbbb cc
$* = aa bbbb cc
  • $@$*の違い
    • $@は位置パラメータがそれぞれ1つずつの文字列として展開される(上記の例では,'aa' 'bbbb' 'cc'として展開)
    • $*は引数全体が1つの文字列として展開されている(上記の例では,'aa bbbb cc'として展開)

if文の制御構造

if-bin.sh
#!/bin/bash

if [ "$1" = "bin" ]; then
	echo "ok"
else
	echo "NG"
fi
$ ./if-bin.sh bin
ok
$ ./if-bin.sh bash
NG

記述の注意点

  • if [ "$1" = "bin" ] then
    ⇒条件を書いた後に;を省略するとエラー(thenを改行すればセミコロン不要)

  • if ["$1" = "bin"]
    []の前後に半角スペースがないとエラー

if文の仕組み

シェルスクリプトでは,if文の後ろに置くのは「コマンド」であって,条件式ではない.
[は単なる括弧ではなく,bashの組み込みコマンド.
[コマンドは引数に書かれた条件式を判定し,その条件が正しければ0,そうでなければ0以外を返すコマンド.if文では0か0以外かどうかで真偽を判定
if直後の文は終了ステータスの値で真偽を判定するため,[コマンド以外でも可能.評価演算子等を組み合わせて活用する.

終了ステータス

終了ステータスとはどういうものか.
lsやgrepコマンドなどは,終了時にある整数値を返す.その整数値のことを終了ステータスという.コマンドが正常に終了した場合は0,エラー時は0以外を返す.
exit status = 0exit status = 1とかの整数値が終了ステータスにあたる.

15
19
2

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
15
19

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?