シェルスクリプトはなんとなく書けるけど,なんとなくしか書けないので,改めて自分用にシェルスクリプトをまとめました.$ から始まる行を実行し,結果を次の行で示します.概ねThe Shell Scripting Tutorialを参考にしています.
実行環境
$ cat /etc/issue Ubuntu 20.04.1 LTS $ bash --version GNU bash, version 5.0.17(1)-release (x86_64-pc-linux-gnu) ...
Hello World!
1個目が命令で,それ以降は引数として解釈される.改行により区別される.
$ echo "Hello World!" Hello World! $ echo "Hello" "World!" Hello World! $ echo Hello World! Hello World!
変数
"=" で変数に代入する."="の前後にスペースを入れてはいけない.$から始めると変数を参照する.
$ MESSAGE="Hello World!" $ echo $MESSAGE Hello World!
" で囲むと文字列になるが,その中で$から始めた部分は変数に置き換わる.
$ NAME=John $ echo "He is $NAME." He is John.
変数は初期化されずに参照すると空になる.エラーは発生しない.
$ echo "VAR is $VAR" VAR is $ VAR=John $ echo "VAR is $VAR" VAR is John
"_"などを使う名前の変数を扱うには{}で囲む.$VAR_1_1
ではどこまでが変数の名前か曖昧なので,${VAR_1}_1
と書く.
$ VAR_1=John $ echo "VAR_1 is ${VAR_1}_1" VAR_1 is John_1
エスケープ文字
一部の記号には特殊な意味がある.スペースは区切りの意味になるので," で囲む."を表示したいときは\を前に付ける.
$ echo Hello World Hello World $ echo "Hello World!" Hello World! $ echo "Hello \"World\"" Hello "World"
* はカレントディレクトリのファイル全てを示す.*vは最後がvで終わる全てのファイルを示す.
$ echo * bin boot dev etc home lib lib32 lib64 libx32 media mnt opt proc root run sbin srv sys tmp usr var $ echo *v dev srv
{ }
でコンマ区切りの文字列を囲むと,展開される.複数あれば順列となる.
$ rm * $ ls $ touch {1,2,3,4}.sh $ ls 1.sh 2.sh 3.sh 4.sh $ rm * $ ls $ touch {a,b,c,d,e}.{txt,csv,html} $ ls a.csv a.html a.txt b.csv b.html b.txt c.csv c.html c.txt d.csv d.html d.txt e.csv e.html e.txt
ループ
for in でリストに対してループする.
$ cat 1.sh for i in 1 2 3 4 5 6 seven 8 nine do echo "i=$i" done $ sh 1.sh i=1 i=2 i=3 i=4 i=5 i=6 i=seven i=8 i=nine
while :
で無限ループする.:
はtrueと評価される.
$ cat 2.sh while : do echo "Type something in (^C to quit)" read INPUT_STRING echo "You typed: ${INPUT_STRING}" done $ sh 2.sh Type something in (^C to quit) Test1 You typed: Test1 Type something in (^C to quit) Test2 You typed: Test2 Type something in (^C to quit) This is a sample message. You typed: This is a sample message. Type something in (^C to quit) ^C
テスト
[
はtest
という名前の命令である.
$ type [ [ is a shell builtin $ which [ /usr/bin/[ $ ls -l /usr/bin/test -rwxr-xr-x 1 root root 55640 Sep 5 2019 /usr/bin/test $ ls -l /usr/bin/[ -rwxr-xr-x 1 root root 59736 Sep 5 2019 '/usr/bin/['
命令なので,ls
と同様,間にスペースが必須である.[$VAR = 0 ]
はエラーとなる.&&
を使って簡単な判断ができる.等しいことを比較するために,=
を使う.==
でも構わないが一般的ではない.
$ VAR=0 $ [ $VAR = 0 ] && echo zero zero $ VAR=1 $ [ $VAR = 0 ] && echo zero $ [$VAR = 0 ] && echo zero bash: [1: command not found
if...then...else...
の構文で条件分岐ができる.if
とthen
の間には改行が必要だが,";"を置いて改行の代わりとすることもできる.
$ cat 3.sh VAR=4 if [ $VAR -lt 0 ];then echo "VAR < 0" else echo "VAR >= 0" fi $ sh 3.sh VAR >= 0
testコマンドにはオプションが多数あり,ファイルの存在を確認したりする(-e
)ことも可能である.
-z
で文字列が空ならばtrueとなり,-n
で文字列が空でなければtrueとなる.これを利用して,RETURNを入力するまでループすることができる.
$ cat 4.sh VAR=0 while [ -n "$VAR" ] do echo "Enter some text. (RETURN to quit)" read VAR if [ -n "$VAR" ]; then echo "You said: $VAR" fi done $ sh 4.sh Enter some text. (RETURN to quit) Test1 You said: Test1 Enter some text. (RETURN to quit) Test2 You said: Test2 Enter some text. (RETURN to quit) This is a sample message. You said: This is a sample message. Enter some text. (RETURN to quit)
特別な変数
$0
は,起動されたスクリプト名である.
$ cat 5.sh echo $0 $ sh 5.sh 5.sh
$1
は1個目の引数を示し,同様に$2
, $3
, ... が存在する.$@
はスクリプト名を除いた引数全てを示す.
$ cat 6.sh echo "\$1=$1" echo "\$2=$2" echo "\$3=$@" $ sh 6.sh $1= $2= $3= $ sh 6.sh 1 two $1=1 $2=two $3=1 two
$$
は実行するプロセスのPIDを示す.
$ echo $$ 1
デフォルト値
:-
は,変数の値がなければ直後の値を返す.変数は変わらない.
$ VAR=1 $ echo "VAR = ${VAR:-2}, $VAR." VAR = 1, 1. $ VAR=0 $ echo "VAR = ${VAR:-2}, $VAR." VAR = 0, 0. $ VAR= $ echo "VAR = ${VAR:-2}, $VAR." VAR = 2, .
:=
は,変数の値がなければ直後の値を代入する.
$ VAR=1 $ echo "VAR = ${VAR:=2}, $VAR." VAR = 1, 1. $ VAR=0 $ echo "VAR = ${VAR:=2}, $VAR." VAR = 0, 0. $ VAR=2 $ echo "VAR = ${VAR:=2}, $VAR." VAR = 2, 2.
Unixコマンド
"`" (バッククォート)で囲むと,コマンドとして実行される.入力に応じたコマンドを実行できるようになる.
$ touch {a,b,c,d,e}.{txt,csv,html} $ ls 7.sh a.csv a.html a.txt b.csv b.html b.txt c.csv c.html c.txt d.csv d.html d.txt e.csv e.html e.txt $ cat 7.sh FILES=`ls *.$1` echo $FILES $ sh 7.sh txt a.txt b.txt c.txt d.txt e.txt $ sh 7.sh html a.html b.html c.html d.html e.html $ sh 7.sh csv a.csv b.csv c.csv d.csv e.csv
{ }
で囲んだ部分は同じプロセスで実行される.( )
で囲んだ部分はサブシェルで実行される.カレントディレクトリを一時的に変更したい時に便利.
$ cat 8.sh echo `pwd` { cd /usr echo `pwd` } echo `pwd` ( cd /home echo `pwd` ) echo `pwd` $ sh 8.sh /home /usr /usr /home /usr
よく使うコマンド
文字列の置換と削除
trコマンドを使う.translateの略で,文字列の置換と削除ができる.範囲が指定できるので,全て大文字/小文字に置換することもできる.
$ echo Hello | tr e E HEllo $ echo Hello | tr a-z A-Z HELLO
-d
で削除する.改行を削除するのに便利.
$ tr --version tr (GNU coreutils) 8.30 Copyright (C) 2018 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later <https://gnu.org/licenses/gpl.html>. This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law. Written by Jim Meyering. $ tr --version | tr -d '\n' tr (GNU coreutils) 8.30Copyright (C) 2018 Free Software Foundation, Inc.License GPLv3+: GNU GPL version 3 or later <https://gnu.org/licenses/gpl.html>.This is free software: you are free to change and redistribute it.There is NO WARRANTY, to the extent permitted by law.Written by Jim Meyering.
気をつけること
スコープは存在しないので,実行される順番に従って処理される.