Y's note

Web技術・プロダクトマネジメント・そして経営について

本ブログの更新を停止しており、今後は下記Noteに記載していきます。
https://note.com/yutakikuchi/

ShellScriptのまとめ

概要

ShellScriptについて簡単にまとめます。
私はzsh使いですが、この記事ではshを中心に書いています。

Shellの種類と特徴

Shell名 特徴
sh 最初のシェル(Bourneシェル)
csh C言語の文法に似たスクリプト用いることができる
bash Bourneシェルを拡張したもの(Bourne Again Shell)
tcsh cshを拡張したもの
ksh 商用UNIX(SystemV)の標準シェル
zsh 最強のシェル(bashtcshの機能を併せ持つ)

基本コマンド

コマンド 説明
Ctrl+H カーソルの左の文字を一文字削除(BSキー)
Ctrl+B カーソルを左に移動
Ctrl+F カーソルを右に移動
Ctrl+D カーソル上の文字を一文字削除(Dellキー)
Ctrl+K カーソルから右側の文字をすべて削除
Ctrl+S 画面への出力を一時停止
Ctrl+Q 画面への出力を再開
Ctrl+L 画面をクリアー
Ctrl+A 行の先頭にカーソルを移動
Ctrl+E 行の最後にカーソルを移動
Ctrl+C プログラムの処理を中止
Ctrl+Z プログラムの処理を一時停止
Ctrl+P 履歴をひとつ前に遡る
Ctrl+N 履歴を逆順の遡る
!! 直前の実行したコマンドを実行
!-n n回前に実行したコマンドを実行
!n history番号のn番号を実行
!<文字列> 文字列から始まるコマンドの最新のものを実行
!?<文字列>? 文字列を含むコマンドの最新のものを実行
history historyの一覧を表示

四則演算子

演算子 説明
+
-
*
/
% 余り

数値評価演算子

演算子 説明
-lt より小さい
-le 以下
-eq 等しい
-ge 以上
-gt より大きい
-ne 等しくない

文字列比較演算子

演算子 説明
= 両辺の文字列が一致したとき真
!= 両辺の文字列が一致しないとき真
-n 変数 変数の長さが0でないときに真
-z 変数 変数の長さが0でであるとき真
! 変数 変数の長さが0でであるとき真

論理演算子

演算子 説明
! cond condが偽のとき真
cond -a cond2 condかつcond2のとき真
cond -o cond2 condまたはcond2のとき真

ファイル属性演算子

※fileという記述のところにファイルパスを指定

演算子 説明
-d file fileが存在してディレクトリのとき真
-e file fileが存在するとき真
-r file fileが読み取り可能なとき真
-w file fileが書き込み可能なとき真
-x file fileが実行可能なとき真
-f file fileが存在し普通のファイルのとき真
-L file fileがシンボリックリンクのとき真
-s file fileサイズが0より大きいとき真
file -nt file2 fileがfile2より新しければ真
file -ot file2 fileがfile2より古ければ真

特殊変数

変数名 説明
$? 最後に実行したコマンドのexit値 0:成功時 1:失敗時
$$ シェル自身のプロセスID
$! シェルが最後に起動したバックグラウンドプロセスのプロセスID
$- シェルの起動時のフラグ、setコマンドを使って設定したフラグの一覧
$n スクリプトに渡された n番目の引数 (9個まで引数を取れる。$0はスクリプトの名前、 $1は第1引数、...、$9は第9引数)
$# シェルに対する引数の個数(引数がない場合は0)
$* 全引数リスト。ダブルクォートで囲んだ場合、"$1 $2 ... $n" と全引数を一つにくっつけた物に展開される。
$@ 全引数リスト。ダブルクォートで囲んだ場合、"$1" "$2" ... "$n" とそれぞれの引数を個別にダブルクォートで囲んで展開する。

1行目のおまじない

#!はシバンといいます。以下のプログラムはこれを使うよという意味です。
http://ja.wikipedia.org/wiki/シバン_(Unix)
#!/bin/sh -x といった-xと指定する事でデバックモードで実行できるようです。

変数の使い方

スペースを入れると文法エラーになる。
#!/bin/sh
a = "JavaScript" #文法エラー
echo $a
シングルクォートとダブルクォートの違い
  1. ダブルクォーテーションはその中にある変数は展開される。
  2. シングルクォーテーションは文字列定数として扱われる。

phpなども同様。

#/bin/sh
echo '$100'
echo "$100"
ブレース展開
  1. 文字列をカンマ区切りで{}でくくるとそれぞれを展開してくれる。
  2. 例はfor文の項目で利用するファイル配布処理。
#!/bin/sh 
list=( local{01,02,03}.devs )
for i in ${list[@]}
do
    scp .ssh $i
done

配列

定義
#!/bin/sh
list=( 1 2 3 )
#以下は上と同義
list[0]=1
list[1]=2
list[3]=3
#参照
echo ${list[0]}
echo ${list[1]}
echo ${list[2]}
for文と利用
  1. 後で項目を挙げるfor文と配列の組み合わせ
  2. ${list[@]}は配列の全要素。
  3. ${#list[@]}となると配列の大きさになる。
#/bin/sh
list=(1 2 3)
total=0
for a in ${list[@]} 
do
  total=`expr $total + $a`
done
echo $total
最後に要素を追加
#/bin/sh
list=(1 2 3)
list=(${list[@]} 10)
echo ${list[@]}
2つ以上の配列のマージ
#/bin/sh
list=(1 2 3)
list2=(4 5 6)
list=(${list[@]} ${list2[@]})
echo "${list[@]}"

文字列

例.二つ以上の文字列を連結させる
#!/bin/sh 
str="Java" 
str2="Script" 
dstr=$str$str2 
echo $dstr 
例.特定文字列の長さを取得
#!/bin/sh 
str="JavaScript" 
len=${#str} 
echo $len 
例.正規表現のマッチ
#!/bin/sh
a="JavaScript"
if [ `expr $a : "Java"` ]
then
    echo "match"
else 
    echo "no match"
fi

if文

例.文字列の空判定
  1. ifと[]の間には半角スペースが必要。
  2. ifとelifの後には必ずthenを記述する。
  3. ifの終了となるfiを記述する。
  4. 慣習的に空文字判定は"x$a" = "x"のように記述する。
#!/bin/sh
a="test" 
if [ "x$a" = "x" ]
then 
    echo "Empty" 
elif [ $a = "test" ]
then
    echo "Match"
else
    echo "Not Match" 
fi

for文

例.ファイルを配布
  1. 連続する数を生成する。
  2. 規則正しいサーバ名に対してファイルを配布する。
  3. echoで表示し |sh で実行する。
#!/bin/sh 
for n in {1..10}
do 
  echo scp .ssh local$n: | sh
done

while文

例.ファイルを配布
  1. for分の例をwhile文で書いてみる。
  2. 数値演算子の-leを使う。
#!/bin/sh 
a=0
while [ $a -le 10 ] 
do 
    echo scp .ssh local$a.devs:
    a=`expr $a + 1` 
done

until文

例.ファイルを配布
  1. for文の例をuntilを使って書く。
#!/bin/sh 
a=0
until [ $a == 11 ] 
do
   echo scp .ssh local$a.dev
   a=`expr $a + 1`
done

case文

例.引数の値から呼び出すコマンドを変える。
  1. case文を利用。
  2. コマンドライン引数を取得
#!/bin/sh 
case $1 in
*.txt) vi $1 ;;
*.jpg|*.jpeg) gimp $1 ;;
*.mp3) xmms $1 ;;
*) echo "I don't know this file." ;;
esac
例.引数に指定されたファイルの文法チェック
#!/bin/sh 
case $1 in
*.php) php -l $1 ;;
*.pl|*.cgi) perl -c $1 ;;
*.sh) sh -n $1 ;;
*) echo "I don't know this file." ;;
esac

関数を使う

例.引数の合計値を出す
  1. コマンドライン引数を取得する$*を利用する。
  2. shiftコマンドを利用して$1の変数が次の引数を参照できるようにする。
#!/bin/sh 
sum()
{
total=0
while [ $# -ne 0 ] 
do
    total=`expr $total + $1`
    shift
done
echo $total
return 0 
}

sum $*

応用

例.はてぶの新着エントリーに掲載されているかどうかを確認
  1. curlgrepの利用
#!/bin/sh 
a=0
acount="yutakikuchi"
baseuri="http://b.hatena.ne.jp/entrylist/it?"
#loop
while [ $a -le 3000 ] 
do 
    result=`curl $baseuri'sort=eid&of='$a` 
    echo $result | grep -i $acount
    if [ $? = 0 ]
    then
        echo $a" hold=0" >> result.txt
    fi
    result=`curl $baseuri'sort=hot&threshold=3&of='$a`
    echo $result | grep -i $acount
    if [ $? = 0 ]
    then
        echo $a" hold=3" >> result.txt
    fi
    result=`curl $baseuri'sort=hot&threshold=5&of='$a`
    echo $result | grep -i $acount
    if [ $? = 0 ]
    then
        echo $a" hold=5" >> result.txt
    fi
    a=`expr $a + 20`
done