トップページに戻る
bashスクリプト文法
最初に:
- bashコマンドには、bashの内部コマンドと、Linuxの実行プログラムである外部コマンドがあります。
内部コマンドの例: cd, echo, pwd, alias, export, readなど
・ cd: ディレクトリを変更
・ echo: 文字列を出力
・ pwd: 現在のディレクトリパスを表示
・ alias - コマンドのエイリアスを定義する
・ unalias: 定義済みのエイリアスを削除する
・ export: 環境変数を設定する
・ set: シェルのオプションや変数を設定する
・ unset: シェルの変数を削除する
・ read: 標準入力から値を読み取る
・ trap: シグナルをキャッチして特定の処理を実行する
外部コマンドの例: test, [, basename, sort, expr, cut, find, grepなど
ほとんどのコマンドが外部コマンドで実現されています。
例えば、if 文では
if [ "$a" = "1" ]; then
となりますが、[ は外部コマンドであり、/bin/testのaliasです。
一方、bash 5から実装された
if [[ "$a" == "1" ]]; then
の [[ は内部コマンド (内蔵構文) です。
- シェバン行:
一般的に、1行目はシェバン行を書き、スクリプトを実行するプログラムを指定する
#!/bin/bash
- 構文単位:
単文: 行末まで
継続行:
行末に \ を書き、改行コードをエスケープする
; により、文を区切り、複数の文を1行に書ける
ブロック構文: 制御構文ごとに異なる。if ~ fi, do ~
done, など
- 環境変数とシェル変数:
bashでは、bashスクリプト内のみ使えるシェル変数が使える。
例: current_dir=`pwd`
その他、LinuxがOSとして記憶している環境変数も参照できる。
bashスクリプトから環境変数を設定するには export
関数を用いる
例: % export PATH=/home/user/bin:$PATH
- 外部コマンドの実行:
・ コマンドと引数を書く
% command arg1 arg2
バックグラウンド実行:
・ Windows: start /B command #
/Bをつけると、新しいコマンドプロンプトを開かずにバックグラウンド実行する
・ Linux: command &
- リダイレクト、パイプ:
コマンドの標準入出力を、ファイルや他のコマンドに切り替える際に使います
command < file # fileから1行ずつcommandが読み込む
command > file # commandの標準出力のみfileへ書き込む
command 1> file # commandの標準出力のみfileへ書き込む
command 2> file # commandの標準エラー出力のみfileへ書き込む
command 1> file1 2> file2 #
commandの標準出力をfile1へ、標準エラー出力をfile2へ書き込む
command &> file #
commandの標準出力と標準エラー出力をfileへ書き込む
>> を使うと追加書き込みになる
コマンドの出力を別のコマンドの入力に綱が得る場合は
パイプ | を使う:
command1 | command2
command1 |& command2
コマンドの出力を出したくない場合:
Windows: command >NUL
Linux: command >/dev/null
- ヒアドキュメント (here document):
<<EOF等と書くと、行頭からEOFまでを複数行の文字列として扱う
content=<<EOF
hello
world
$var
EOF
上の場合は変数$varが展開されますが、'EOF'とすると展開されません
content=<<'EOF'
hello
world
$var
EOF
- 代表的な環境変数、シェル変数:
・ HOME: ユーザーのホームディレクトリ
・ PATH: 実行可能ファイルの検索パス
・ USER: 現在のユーザー名
・ SHELL: 現在のシェルのパス
・ LANG: ロケール設定
・ PWD: 現在の作業ディレクトリ
・ OLDPWD: 前の作業ディレクトリ
・ EDITOR: デフォルトのテキストエディタ
・ EPOCHSECONDS: 1970年1月1日からの秒数
・ EPOCHREALTIME: 1970年1月1日からの秒数をマイクロ秒単位で返す
- 位置パラメータ:
・ $0: スクリプトの名前
・ $1, $2, ...: コマンドライン引数
・ $#: 引数の数
・ $@: すべての引数(個別に引用符で囲まれる)
・ $*: すべての引数(単一の文字列として)
引数シフト:
shift を使うと、$1を削除して、$2, $3, ... を $1, $2,
... にシフトする
- 特殊変数:
・ $?: 前回実行したコマンドの終了ステータス
・ $$: 現在のシェルのプロセスID
・ $!:
最後にバックグラウンドで実行されたコマンドのプロセスID
・ $-: 現在のシェルのオプションフラグ
・ $_: 最後に実行したコマンドの最後の引数
- コマンドラインオプション解析: getopts
- 別のbashスクリプトを現在のシェルで実行: source, .
上記のシェル変数で説明したように、シェルスクリプトで設定した変数は、そのシェルスクリプト以外では使えません。
シェルスクリプトAから別のシェルスクリプトBを呼び出し、Bでシェル変数を設定しても、Bが終了してAに戻ってきたとき、
Aからはそれらの変数を参照できません。
source コマンド (あるいは単に . )
で呼び出すと、Aが実行されているシェルでBが実行されるため、
Aからも、Bで設定したシェル変数などを参照できます。
- 古い比較演算子: 推奨しない
数値比較: -eq, -ne, -lt, -le, -gt, -ge
文字比較: =, !=
論理演算: -a, -o
testコマンド [ を使って以下のように書く
if [ "$a" -ne "1" ]; then
- 比較演算子: bash 5以降
[[ ... ]] を使う場合、以下の演算子が使える
数値比較: -eq, -ne, -lt, -le, -gt, -ge
あるいは、文字列として比較する
文字列比較: ==, !=, <, > (辞書順で比較)
論理演算: &&, ||
正規表現: if [[ "$a" =~ ^[0-9]+$ ]]; then
ワイルドカード: if [[ "$string" == *"world"* ]];
then など
- 簡単な計算:
(( 数式 ))
例: result = $(( a + b )) #
スペースはあってもなくてもいい
使える演算子:
・ 四則演算: +, -, *, /, %
・ インクリメント/デクリメント: ++, --
・ 比較演算: <, <=, >, >=, ==, !=
・ ビットシフト: <<, >>
・ ビット論理演算: &, |, ^, ~
・ 論理演算: &&, ||, !
- 複雑な計算:
exprコマンドなどを使う
・ result = $(expr $a +
$b)
# 四則演算のみなので、(())を使うのであれば不要
。スペースは必須(引数を分離する必要がある)
・ result = $(echo "$a + $b" | bc)
# 数学関数も使える
sqrt(16): 平方根
e(1.0): 指数関数
l(10): 自然対数
s(0), c(0), a(1.0): 三角関数 (sin, cos, atan)
・ result = $(awk "BEGIN {print $a + $b}") # awkは perlやpythonの簡易版のような軽量スクリプト言語なので、数学関数なども使える
- 条件分岐:
if [[ 条件構文 ]]; then
...
elif [[ 条件構文2 ]]; then
...
else
...
fi
- case構文:
case "$variable" in
pattern1)
# pattern1に一致した場合の処理
;; # caseの処理を終了
#
;;が無い場合、pattern2以降の判定を継続実行してしまう
pattern2)
# pattern2に一致した場合の処理
;;
*)
# どのパターンにも一致しない場合の処理
;;
esac
- 配列の宣言:
array="41667 43333 45000 46667 48333 50000"
array=(one two three)
for element in "${array[@]}"; do
echo "$element"
done
- 連想配列 (辞書型) の宣言:
declare -A associative_array
associative_array = ( ["key1"]="value1"
["key2"]="value2" )
for key in "${!associative_array[@]}"; do
...
done
- ブレース展開:
{1..10} # 1~10の整数に展開
{1..10..2} # 1~10まで2つ飛ばしで 1 3 5 7 9 に展開
{aa,bb,cc} # aa bb ccに展開
file.{txt,bak} # file.txt file.backに展開
file{1..3}.txt # file1.txt file2.txt file3.txtに展開
- 繰り返し:
for var in 配列; do
...
done
while read line
do
...
done
until [[ $i -eq 10 ]]
do
...
done
for ((ix = 0; ix < $nx; ix++)) {
ixm1=`expr $ix - 1`
xm1=${xarray[$ixm1]}
x=${xarray[$ix]}
}
- 選択肢を表示し、入力を受け取る:
select i in Red Green Blue
do
case $i in
Red) echo "Red!!"; break ;;
Green) echo "Green!!"; break ;;
Blue) echo "Blue!!"; break ;;
*) echo "Bad select!!" ;;
esac
done
- ループ制御:
・ break: もっとも内側のループを抜ける
・ continue: 最も内側のループを次の繰り返しに移す
- 関数:
myfunc() {
... # 引数は$0, $1, ..., $*, $@, $#で参照する
return ret_val # 戻り値を返すことができる
}
呼び出し
myfunc arg1 arg2 arg3
# 戻り値は $? で受け取る