見出し画像

bashの記述を見直そう!


はじめに

Software Design 2024年12月号の特集「シェルスクリプトの基本と罠」を読んでいたのですが、シェルの記述方式をちゃんと理解していないことに気づきまして、改めて勉強し直そうと各種記述を以下にまとめました。

特殊パラメータ

$0: シェルスクリプト名

サンプル

#!/bin/bash
echo '$0:' $0

結果

~/bash$ ./sample_args.sh a1 a2 a3  
$0: ./sample_args.sh

$1~9: シェルスクリプトに渡される引数

サンプル:10以降の引数は${10}のように波括弧を付けて表現します。

#!/bin/bash
echo '$1:' $1

結果

~/bash$ ./sample_args.sh a1 a2 a3 
$1: a1

$*: シェルスクリプトに渡される引数全て

サンプル

#!/bin/bash
echo '$*:' $*
for arg in "$*";do echo $arg; done;

結果:$*は引数がひとまとまりとして扱われます。

~/bash$ ./sample_args.sh a1 a2 a3  
$*: a1 a2 a3
a1 a2 a3

$@: シェルスクリプトに渡される引数全て

サンプル

#!/bin/bash
echo '$@:' $@
for arg in "$@";do echo $arg; done;

結果:$@は引数が別々に扱われます。

~/bash$ ./sample_args.sh a1 a2 a3  
$@: a1 a2 a3
a1
a2
a3

$#: シェルスクリプトに渡される引数の数

サンプル

#!/bin/bash
echo '$#:' $#

結果

~/bash$ ./sample_args.sh a1 a2 a3  
$#: 3

$?: 最後に実行したコマンドの終了ステータス

サンプル

#!/bin/bash
echo '$?:' $?

結果:echoの正常終了ステータスなので0

~/bash$ ./sample_args.sh a1 a2 a3  
$?: 0

$$: シェルスクリプトのPID

サンプル

#!/bin/bash
echo '$$:' $$

結果

~/bash$ ./sample_args.sh a1 a2 a3  
$$: 50666

パラメータの展開

${parameter:-word} parameterが未設定であればwordを使用。parameterへの代入はなし

サンプル

#!/bin/bash
export parameter="word-parameter-word"
echo '${parameter:-word}:' echo ${parameter:-word}
echo 'parameter:' $parameter
unset parameter
echo '${parameter:-word}:' echo ${parameter:-word}
echo 'parameter:' $parameter

結果

~/bash$ ./sample_param.sh 
${parameter:-word}: echo word-parameter-word
parameter: word-parameter-word
${parameter:-word}: echo word
parameter:

${parameter:=word} parameterが未設定であればwordを使用。parameterへの代入あり

サンプル

#!/bin/bash
export parameter="word-parameter-word"
echo '${parameter:=word}:' echo ${parameter:=word}
echo 'parameter:' $parameter
unset parameter
echo '${parameter:=word}:' echo ${parameter:=word}
echo 'parameter:' $parameter

結果

~/bash$ ./sample_param.sh 
${parameter:=word}: echo word-parameter-word
parameter: word-parameter-word
${parameter:=word}: echo word
parameter: word

${parameter:+word} parameterが設定されていればwordを使用。未設定であれば空文字。parameterへの代入あり【注意!】

サンプル

#!/bin/bash
export parameter="word-parameter-word"
echo 'parameter:' $parameter
echo '${parameter:+word}:' echo ${parameter:+word}
unset parameter
echo '${parameter:+word}:' echo ${parameter:+word}
echo 'parameter:' $parameter

結果:なお":+"は本来parameterへの代入があるとのことですが、実施したwsl2だと正しく代入されません。実行環境によって違うのかも知れませんので、使用時はご注意ください。

~/bash$ ./sample_param.sh 
parameter: word-parameter-word
${parameter:+word}: echo word
${parameter:+word}: echo
parameter:

${parameter+word} parameterが未設定であればwordを使用。未設定であれば空文字。parameterへの代入なし

サンプル

#!/bin/bash
export parameter="word-parameter-word"
echo 'parameter:' $parameter
echo '${parameter+word}:' echo ${parameter+word}
unset parameter
echo '${parameter+word}:' echo ${parameter+word}
echo 'parameter:' $parameter

結果

parameter: word-parameter-word
${parameter+word}: echo word
parameter: word-parameter-word
${parameter+word}: echo
parameter:

${parameter:?word} parameterが未設定であればwordをエラーとして出力

サンプル

#!/bin/bash
export parameter="word-parameter-word"
echo 'parameter:' $parameter
echo '${parameter:?word}:' echo ${parameter:?word}
unset parameter
echo '${parameter:?word}:' echo ${parameter:?word}

結果:unsetしてparameterを未設定にするとエラーが発生します。また"$?"も終了ステータスが1になります。

parameter: word-parameter-word
${parameter:?word}: echo word-parameter-word
./sample_param.sh: line 40: parameter: word

~/bash$ echo $?
1

${parameter%word} 最短一致した接尾辞のパターンを削除する

サンプル

#!/bin/bash
export parameter="word-parameter-word"
echo '${parameter%word}:' echo ${parameter%word}

結果

~/bash$ ./sample_replace.sh 
${parameter%word}: echo word-parameter-

${parameter#word} 最短一致した接頭辞のパターンを削除する

サンプル

#!/bin/bash
export parameter="word-parameter-word"
echo '${parameter#word}:' echo ${parameter#word}

結果

~/bash$ ./sample_replace.sh 
${parameter#word}: echo -parameter-word

${parameter#offset} parameterからoffset(0始まり)以降の文字列を抜き出す

サンプル

#!/bin/bash
export parameter="word-parameter-word"
echo '${parameter#offset}:' echo ${parameter#6}

結果

~/bash$ ./sample_replace.sh 
${parameter#offset}: echo word-parameter-word

${#parameter} parameterの文字数をカウント

サンプル

#!/bin/bash
export parameter="word-parameter-word"
echo '${#parameter}:' echo ${#parameter}

結果

~/bash$ ./sample_replace.sh 
${#parameter}: echo 19

${#parameter/pattern/string} parameterでpatternにマッチした部分をstringに置換 (1回のみ)

サンプル

#!/bin/bash
export parameter="word-parameter-word"
echo '${#parameter/pattern/string}:' echo ${parameter/a/A}

結果

~/bash$ ./sample_replace.sh 
${#parameter/pattern/string}: echo word-pArameter-word

${#parameter//pattern/string} parameterでpatternにマッチした部分をstringに置換 (全て)

サンプル:"[ ]"でorは実現できますが、正規表現自体は使用不可みたいです。

#!/bin/bash
export parameter="word-parameter-word"
echo '${#parameter//pattern/string}:' echo ${parameter//[ao]/X}

結果

~/bash$ ./sample_replace.sh 
${#parameter//pattern/string}: echo wXrd-pXrXmeter-wXrd

if文のオプション

equal判定

サンプル

#!/bin/bash
export parameter="sample"
if [ ${parameter} = "sample" ]; then 
    echo "equalでture"
fi

結果

equalでture

not equal判定

サンプル

#!/bin/bash
export parameter="sample"
if [ ${parameter} != "sample2" ]; then 
    echo "not equalでture"
fi

結果

not equalでture

文字列長が 大なら true

サンプル

#!/bin/bash
export parameter="sample"
if [ -n ${parameter} ]; then 
    echo "文字列長が 大なら true"
fi

結果

文字列長が 大なら true

文字列長が 0 なら true

サンプル

#!/bin/bash
export parameter=""
if [ -z ${parameter} ]; then 
    echo "文字列長が 0 なら true"
fi

結果

文字列長が 0 なら true

ファイルとディレクトリの判定:ファイル-f/ディレクトリ-d/存在有無-e/サイズ-s/読み-r/書き-w/実行-x/による判定

ファイル(sample.txt)とディレクトリ(sample)を以下のように用意しています。

~/bash$ ls -l
drwxr-xr-x 2 sample sample 4096 Dec 31 15:34 sample
-rw-r--r-- 1 sample sample    6 Dec 31 15:41 sample.txt

サンプル

#!/bin/bash
export file="sample.txt"
if [ -f ${file} ]; then 
    echo "${file} がファイルなら true"
fi
if [ ! -d ${file} ]; then 
    echo "${file} がディレクトリでないなら true"
fi
if [ -e ${file} ]; then 
    echo "${file} が存在するなら true"
fi
if [ -s ${file} ]; then 
    echo "${file} のサイズが 0 より大きければ"
fi
if [ -r ${file} ]; then 
    echo "${file} が読み取り可能なら true"
fi
if [ -w ${file} ]; then 
    echo "${file} が書き込み可能なら true"
fi
if [ ! -x ${file} ]; then 
    echo "${file} が実行可能でないなら true"
fi

export dir="sample"
if [ ! -f ${dir} ]; then 
    echo "${dir} がファイルでないなら true"
fi
if [ -d ${dir} ]; then 
    echo "${dir} がディレクトリなら true"
fi
if [ -s ${dir} ]; then 
    echo "${dir} のサイズが 0 より大きければ"
fi
if [ -e ${dir} ]; then 
    echo "${dir} が存在するなら true"
fi
if [ -r ${dir} ]; then 
    echo "${dir} が読み取り可能なら true"
fi
if [ -w ${dir} ]; then 
    echo "${dir} が書き込み可能なら true"
fi
if [ -x ${dir} ]; then 
    echo "${dir} が実行可能なら true"
fi

結果

sample.txt がファイルなら true
sample.txt がディレクトリでないなら true
sample.txt が存在するなら true
sample.txt のサイズが 0 より大きければ
sample.txt が読み取り可能なら true
sample.txt が書き込み可能なら true
sample.txt が実行可能でないなら true
sample がファイルでないなら true
sample がディレクトリなら true
sample のサイズが 0 より大きければ
sample が存在するなら true
sample が読み取り可能なら true
sample が書き込み可能なら true
sample が実行可能なら true

参考

参考サイトを以下に記載します。
[Bash]特殊変数とパラメータ展開
【シェルスクリプトBash】 if 文(test文)のオプションまとめ


いいなと思ったら応援しよう!