Bash 技術
条件分岐
- 変数
varの内容が0の場合はsuccess、0以外の場合はfailと表示する。
[ "${var}" -eq "0" ] && echo "success" || echo "fail"
- 上記をシェルスクリプト形式で書く場合。
if [ "${var}" -eq "0" ]; then
echo "success"
else
echo "fail"
fi
数値比較
| 数値比較演算子 | 概要 |
|---|---|
数値1 -eq 数値2 |
数値1と数値2が等しければ真 |
数値1 -ge 数値2 |
数値1が数値2より大きい、または等しければ真 |
数値1 -gt 数値2 |
数値1が数値2より大きければ真 |
数値1 -le 数値2 |
数値1が数値2より小さい、または等しければ真 |
数値1 -lt 数値2 |
数値1が数値2未満であれば真 |
数値1 -ne 数値2 |
数値1と数値2が等しくなければ真 |
文字列比較
| 文字列比較演算子 | 概要 |
|---|---|
文字列 |
文字列の長さが 0 より大きければ真 |
-n 文字列 |
文字列の長さが 0 より大きければ真 |
! 文字列 |
文字列の長さが 0 であれば真 |
-z 文字列 |
文字列の長さが 0 であれば真 |
文字列1 == 文字列2 |
2つの文字列が等しければ真(= でも可) |
文字列1 != 文字列2 |
2つの文字列が等しくなければ真 |
文字列1 =~ パターン |
文字列がパターン(拡張正規表現)にマッチすれば真 |
拡張正規表現
| 正規表現 | 概要 |
|---|---|
^ |
行頭 |
$ |
行末 |
. |
任意の文字 |
* |
0文字以上 |
{n} |
n文字(文字数) |
ファイルチェック
| ファイルチェック演算子 | 概要 |
|---|---|
-d ファイル名 |
ディレクトリなら真 |
-f ファイル名 |
通常ファイルなら真 |
-L ファイル名 |
シンボリックリンクなら真 |
-r ファイル名 |
読み取り可能なファイルなら真 |
-w ファイル名 |
書き込み可能なファイルなら真 |
-x ファイル名 |
実行可能なファイルなら真 |
-s ファイル名 |
サイズが 0 より大きければ真 |
ファイル1 -nt ファイル2 |
ファイル1がファイル2より新しければ真 |
ファイル1 -ot ファイル2 |
ファイル1がファイル2より古ければ真 |
条件式の論理結合
| 条件式 | 概要 |
|---|---|
! 条件 |
条件式が偽であれば真 |
条件1 -a 条件2 |
両方の条件式が真であれば真(and) |
条件1 -o 条件2 |
いずれかの条件式が真であれば真(or) |
case 文
$fruit の内容によって処理内容を分岐する。
fruit="apple"
case $fruit in
apple) echo "It's an apple";;
banana) echo "It's a banana";;
*) echo "It's something else";;
esac
ループ
- 1秒間隔で
Hello, Worldを表示する。
while true; do
echo "Hello, World"
sleep 1
done
- 1から5まで表示する。
for i in {1..5}; do
echo "$i"
done
チルダ展開
- Linux ユーザー
user01のホームディレクトリへ移動する。
cd ~user01
ブレース展開
- 1から5まで表示する。
echo {1..5}
-
aからzまでアルファベットを表示する。
echo {a..z}
算術展開
算術展開(3通り)
echo $((1 + 1))
expr 1 + 1
let "result = 1 + 1"
echo "$result"
10進数の100を16進数へ変換する
echo "ibase=10; obase=16; 100" | bc
変数展開
用途の決まっている変数
| 変数 | 概要 |
|---|---|
$0 |
実行中のスクリプト名 |
$1 ~ $9
|
スクリプトに渡された引数。2桁以上はブレース括弧を利用する |
$# |
スクリプトに渡された引数の数 |
$@ |
スクリプトに渡された引数をスペースで区切って展開したもの |
$* |
スクリプトに渡された引数をすべてまとめたもの |
$? |
直前に実行されたコマンドの終了ステータス |
$$ |
スクリプトのプロセスID |
$_ |
直前のコマンドの引数が入る |
パラメータ展開
- 変数
nameが未定義または空文字の場合、Guestを利用する(変数には格納しない)。
echo "Hello, ${name:-Guest}"
- 変数
nameが定義済みならその値を、未定義または空文字ならGuestを使う(変数に格納される)。
echo "Hello, ${name:=Guest}"
- 変数
nameが定義済みならその値を、未定義ならGuestを使う(変数に格納される)。
echo "Hello, ${name=Guest}"
- 変数
nameが定義済みならその値を、未定義ならGuestを使う(変数に格納されない)。
echo "Hello, ${name-Guest}"
- 変数
nameの値が未定義または空文字の場合、エラーを表示して強制終了する。
echo "${name:?}" # デフォルトのエラーメッセージ
echo "${name:?error message}" # エラーメッセージを設定
- 変数の値が定義されている場合、指定した文字列に置換する(変数へは代入しない)。
echo "${name:+string}"
- 変数の値が定義されている場合、指定した文字列に置換する(変数へは代入しない)。
echo "${name+string}"
配列の全要素を表示する
echo "${arr[@]}"
文字列の一部を表示する
sentence="The quick brown fox"
echo "${sentence:4}" # 4番目の文字以降を表示
echo "${sentence:4:5}" # 4番目の文字から5文字分を表示
パターンとして利用できる文字
| 文字 | 概要 |
|---|---|
* |
任意の文字列 |
? |
任意の一文字 |
[...] |
括弧内のいずれか |
# |
先頭からマッチ |
% |
末尾からマッチ |
特定文字を削除して表示する
string="abcABC123ABCabc"
# 最初にマッチする "ABC" より前を削除(ABCを含む)
echo "${string#*ABC}"
# 変数の最初にマッチした文字列を削除
echo "${string##*ABC}"
# 変数の最後からマッチした文字列を削除
echo "${string%ABC*}"
# 変数の最後から最長一致する文字列を削除
echo "${string%%ABC*}"
文字列置換
sentence="I love apples, and apples are tasty."
# 最初に見つかった "apple" を "oranges" に置換
echo "${sentence/apple/oranges}"
# すべての "apples" を "oranges" に置換
echo "${sentence//apples/oranges}"
変数の文字列長を表示する
word="Hello"
echo "${#word}"
特殊変数
| 特殊変数 | 概要 |
|---|---|
BASH |
現在実行中の Bash へのフルパス |
BASH_LINENO |
呼び出し元シェルスクリプトの行番号(配列) |
BASH_VERSION |
現在実行中の Bash のバージョン |
HOSTNAME |
現在のホスト名 |
IFS |
シェルの区切り文字。デフォルトはスペース・タブ・改行など |
LANG |
ロケールのデフォルト。利用可能なロケールは locale -a で確認可能 |
LINENO |
現在実行しているシェルスクリプトの行番号 |
OLDPWD |
1つ前の作業ディレクトリ |
PATH |
シェルがコマンドを探すディレクトリ。複数指定は : で区切る |
PPID |
シェルの親プロセスID |
PS1 |
プロンプト |
PWD |
現在の作業ディレクトリ |
RANDOM |
0 ~ 32767 のランダム整数。値を代入すると初期化される |
SECONDS |
シェルが起動されてからの秒数 |
配列
配列の作成と展開
fruits=("apple" "orange" "banana")
echo "${fruits[0]}"
echo "${fruits[1]}"
echo "${fruits[2]}"
関数
関数の定義と呼び出し
test_def() {
echo "$1"
}
test_def "Hello World"
ヒアドキュメント
新規ファイルの作成
cat << 'EOF' > test.txt
Hello! World
EOF
履歴展開
- 直前に実行したコマンドを再実行する。
!!
-
historyコマンドのコマンド番号を指定して実行する。
!n
- 最後に入力されたコマンドの中で、指定した文字列を含むコマンドを再実行する。
!string
- 直前に実行したコマンドから数えて
n番目のコマンドを実行する。
!-n
プロセス置換
command1 と command2 の実行結果を引数にする
diff <(command1) <(command2)
ls の結果を変数 var に格納する
var=$(ls)
リダイレクト
標準出力をファイルに書き込む
ls 1> output.txt
エラー出力をファイルに書き込む
ls 2> output.txt
標準出力とエラー出力をファイルに書き込む
ls &> output.txt
ファイルに追記する
ls >> output.txt
制御演算子
| 記号 | 概要 |
|---|---|
; |
CommandA の実行後に CommandB を実行する |
& |
CommandA と同時に CommandB を実行する |
| |
CommandA の実行結果を CommandB に渡す |
&& |
CommandA の実行が成功した際に CommandB を実行する |
|| |
CommandA の実行が失敗した際に CommandB を実行する |
利用方法
CommandA <演算子> CommandB
パス名展開
- 任意の文字列(0文字以上)と一致する。
ls *.txt
- 任意の1文字と一致する。
ls file?.txt
- ブラケット内のいずれかの文字と一致する。
ls file[12].txt
- カンマで区切られた複数の文字列と一致する。
echo {apple,orange,banana}-fruit.txt
Tips
最後の値を表示する
echo "${var:${#var} - 1:1}"
フルーツ名のディレクトリ配下に日付+連番のディレクトリを作成する
mkdir -p {apple,banana,berry}/$(date '+%Y%m%d')-{1..5}
カンマ区切りの値を配列 array に格納する
string="apple,orange,banana,grape"
IFS=',' read -ra array <<< "$string"
IPアドレスを取得する
ip -4 addr | awk '/^[0-9]:/{ifname=$2}/inet/{print ifname,$2}' | column -t
ファイルをBase64でエンコード・デコードしてコピーする
# エンコード
tar zcf - file1 file2 | base64
# デコード
cat | base64 -d | tar zxvf -