見出し画像

シェルスクリプト②

前回


文法

シェルスクリプト(特に Bash を基準に)の文法は多岐にわたり、多くのコンセプトと構文要素を含みます。以下に主要なものを列挙しますが、これはすべてを網羅したものではありません。

変数の宣言と使用

VARIABLE_NAME="value"
echo $VARIABLE_NAME

コマンド置換

RESULT=$(command)

算術演算

(( result = 1 + 2 ))

条件式 (if, else, elif)

if [ 条件式 ]; then
  # 条件式が真の場合のコマンド
elif [ 別の条件式 ]; then
  # 別の条件式が真の場合のコマンド
else
  # それ以外の場合のコマンド
fi

ループ (for, while, until)

for i in {1..5}; do
  echo "Number $i"
done

while [ 条件式 ]; do
  # 条件式が真の間、コマンドを繰り返す
done

until [ 条件式 ]; do
  # 条件式が偽の間、コマンドを繰り返す
done

ケース文 (case)

case $VARIABLE in
  pattern1)
    # パターン1にマッチした場合のコマンド
    ;;
  pattern2)
    # パターン2にマッチした場合のコマンド
    ;;
  *)
    # どのパターンにもマッチしない場合のコマンド
    ;;
esac

関数の定義と使用

my_function() {
  echo "Hello, World!"
}

my_function

リダイレクト (>, >>, <, |)

echo "Hello" > file.txt  # ファイルへの出力
cat file.txt >> another_file.txt  # ファイルへの追記
cat < file.txt  # ファイルからの入力
command1 | command2  # パイプライン

エラーハンドリング (set, trap, exit)

set -e  # エラーが発生した場合にスクリプトを終了
trap 'echo Error at about $LINENO' ERR  # エラーハンドラー
exit 1  # スクリプトを終了し、ステータス1を返す

ワイルドカードとグロビング

*.txt  # txtで終わるファイル

特殊変数 ($0, $1, $#, $@, $?, $$, $!)

  • $0: スクリプト名

  • $1, $2, ...: 引数

  • $#: 引数の数

  • $@: すべての引数

  • $?: 直前のコマンドの終了ステータス

  • $$: 現在のプロセスID

  • $!: 最後に実行されたバックグラウンドプロセスのID

文字列とパラメータ展開

  • "${VARIABLE:-default}": VARIABLE が未設定または空の場合、default を使用

  • "${VARIABLE:+alt_value}": VARIABLE が設定されている場合、alt_value を使用

  • "${VARIABLE:offset:length}": VARIABLE の部分文字列

配列と連想配列

ARRAY=("item1" "item2" "item3")
declare -A ASSOC_ARRAY=( ["key1"]="value1" ["key2"]="value2" )

ファイルとディレクトリのテスト (-f, -d, -e 等)

if [ -f "$FILE" ]; then
  # ファイルが存在する場合
fi

  1. 拡張グロビング

    • `?(pattern-list)`, `*(pattern-list)`, `+(pattern-list)`, `@(pattern-list)`, `!(pattern-list)`: ワイルドカードを使ったより複雑なパターンマッチング。

  2. ブレース展開

    • `{a,b,c}`, `{1..10}`, `{a..z}`: 文字列や数値のシーケンスを生成するための展開。

  3. プロセス置換

    • `< <(command)`, `> >(command)`: コマンドの出力をファイルのように扱うための構文。

  4. ヒアドキュメント (Here Documents)

    • `<<[delimiter]` と `delimiter` を使って、複数行の入力をリダイレクトする。

  5. ヒアストリング (Here Strings)

    • `<<< word`: 単一の単語や文字列を標準入力にリダイレクトする。

  6. 条件式の拡張

    • `[[ 条件式 ]]`: Bash におけるより高度な条件式の構文。

  7. セレクト構文 (`select`)

    • メニューからの選択を可能にするためのループ構文。

  8. 算術展開

    • `$(( expression ))`: 算術式の評価と展開。

  9. サブシェル

    • `(commands)`: 新しいサブシェル内でコマンドを実行。

  10. コマンドグループ

    • `{ commands; }`: 現在のシェル内でコマンドグループを実行。

  11. テストコマンド (`test`、`[ ]`)

    • ファイル属性のテスト、文字列の比較、算術比較など。

  12. シェルオプション

    • `set -o option`, `shopt -s option`: シェルの挙動を制御するオプション。

  13. バックグラウンド処理

    • `command &`: コマンドをバックグラウンドで実行。

  14. ジョブ制御

    • `fg`, `bg`, `jobs`: バックグラウンドプロセスやジョブの管理。

  15. シェルパラメータの展開

    • `${parameter:-word}`, `${parameter:=word}`, `${parameter:?word}`, `${parameter:+word}`: パラメータが設定されていない場合のデフォルト動作。

  16. 配列の操作

    • 配列要素の追加、削除、部分的な取得、長さの取得など。

  17. 関数のスコープとローカル変数

    • `local variable`: 関数内でのローカル変数の定義。

  18. シグナルとトラップ

    • `trap 'commands' SIGNAL`: 特定のシグナルが受信されたときにコマンドを実行。

  19. リードコマンド (`read`)

    • 標準入力または他のファイルからの入力の読み取り。

  20. タイプコマンド (`type`)

    • コマンドや関数、ファイル等のタイプを表示。

ダラー

シェルスクリプト、特に Bash や他の Unix/Linux ベースのシェルにおいて、ダラー記号(`$`)は主に変数を参照するために使用されます。以下に、その一般的な使用法を説明します。

  1. 変数の参照: `$` 記号は変数の値を取得するために使用されます。例えば、変数 `name` がある場合、その値を取得するには `$name` と書きます。これは変数 `name` の現在の値をスクリプトのその部分に展開します。

  2. 特殊変数: いくつかの特殊変数も `$` 記号を使ってアクセスされます。例えば、`$?` は直前に実行されたコマンドの終了ステータスを返し、`$$` は現在のシェルプロセスのプロセスIDを返します。

  3. パラメータ展開: `$` はパラメータ展開にも使われます。これには変数の値を変更する機能や、変数が設定されているかどうかをチェックする機能などがあります。例えば、`${variable:-default}` は `variable` が設定されていない場合に `default` を使います。

  4. コマンド置換: `$()` はコマンド置換に用いられ、カッコ内のコマンドの出力を取得します。例えば、`$(date)` は現在の日付を取得します。

  5. 算術展開: `$(( expression ))` は算術演算のために使われ、式 `expression` の結果を返します。

シェルスクリプト(特に Bash)において、変数名にダラー記号(`$`)が付かない場合、その変数は「代入」されるか「宣言」されると解釈されます。具体的には、以下のような振る舞いが期待されます:

  1. 変数の代入: 変数に値を代入するときは、ダラー記号を使いません。例えば、`name="John"` というコードは `name` という変数に文字列 `"John"` を代入しています。

  2. 変数の宣言: 変数を作成する際にも、ダラー記号は使用しません。例えば、`declare -i number` は整数型の変数 `number` を宣言しています。

一方で、変数の値を参照する(読み出す)際には、その変数名の前にダラー記号を付けます。例えば、`echo $name` は `name` 変数の値を出力します。

このように、変数にダラー記号が付いているかどうかは、その変数を「読み取る」か「書き込む」かを区別するための重要な手がかりとなります。変数の値を操作する際には、この違いを正しく理解することが重要です。

ブレース

Bash スクリプトにおける `{}` は、カーリーブレース(波括弧)と呼ばれ、複数の用途がありますが、基本的には変数の名前やリテラルの一部を区切るために使用されます。特に、変数名とその後ろに続く文字列を区別する場合に役立ちます。例を挙げて説明します。

  1. 変数名の明確化: `${var}iable` のように使用される場合、`${var}` は `var` という変数を参照し、`iable` はその後に続く単なる文字列です。この場合、波括弧は `var` と `iable` が別々のものであることを明確にします。変数名と後続する文字の間の区別が不要な場合(例えば `$var` だけの場合)は、波括弧を省略できます。

  2. パラメータ展開: Bash では、波括弧内に特定の構文を使用して、変数の値を変更したり情報を取得したりすることができます。例えば、`${#var}` は変数 `var` の長さを返します。

  3. ブレース展開: `{a,b,c}` のように使用される場合、これは `a`、`b`、`c` の各要素に対して同じ操作を行うためのものです。例えば、`file_{a,b,c}.txt` は `file_a.txt file_b.txt file_c.txt` と展開されます。

  4. デフォルト値: `${var:-default}` のように使用されると、`var` が未設定または空の場合に `default` を使用します。

これらは Bash の `{}` の使い方の一部の例です。コンテキストによって意味が異なるため、具体的なスクリプトの内容を見ながら解釈する必要があります。

コマンド置換

コマンド置換は、シェルスクリプトにおいて、あるコマンドの出力を取得し、それを別のコマンドの引数や変数の値として使用するための機能です。コマンド置換を使用すると、一つのコマンドの実行結果を直接別のコマンドに渡すことができます。
コマンド置換には主に二つの構文があります:

バッククォート (`) を使用する方法

result=`command`

この方法では、バッククォート(`)でコマンドを囲みます。この構文は古い形式ですが、多くのシェルスクリプトで依然として使われています。

ドル記号と丸括弧 ($) を使用する方法

result=$(command)

この方法では、ドル記号 ($) に続けて丸括弧でコマンドを囲みます。この構文は現代のシェル(特に Bash)で推奨されており、ネストされたコマンド置換を行う際に読みやすくなります。

コマンド置換の一般的な用途には以下のようなものがあります:

  • コマンドの出力を変数に代入する。

  • コマンドの出力を別のコマンドの引数として使用する。

  • ファイル名やディレクトリ名などを動的に生成する。

例:

# ディレクトリのリストを変数に格納
directories=$(ls -d */)

# ファイルの行数をカウントして表示
line_count=$(wc -l < file.txt)
echo "The file has $line_count lines."

このように、コマンド置換はシェルスクリプトの柔軟性とパワーを大いに高める機能です。

算術演算

シェルスクリプト、特に Bash において、算術演算はいくつかの方法で行うことができます。これは基本的な数学的演算(加算、減算、乗算、除算など)を行うために使用されます。以下に主な方法を紹介します。

二重丸括弧 ((...)) の使用

Bash では ((...)) 構文を使用して算術演算を行うことができます。これはシェルによって特別に扱われ、算術式として解釈されます。

(( result = 1 + 2 )) echo $result # 出力: 3

let コマンドの使用

let コマンドもまた算術演算に使用できます。これは式を評価し、結果を変数に代入します。

let result=1+2 echo $result # 出力: 3

算術展開 $((...)) の使用

$((...)) 構文は算術演算を行い、その結果を展開して返します。これは文字列中で使われることが多いです。

result=$((1 + 2)) echo $result # 出力: 3

expr コマンドの使用

古いスタイルのシェルスクリプトでは expr コマンドが算術演算に使われることがあります。このコマンドは引数として与えられた式を評価します。

result=$(expr 1 + 2) echo $result # 出力: 3

Bash における算術演算では、基本的な四則演算の他にも、剰余演算(%)、指数演算(**)、ビット演算(ビットごとの AND &、OR |、XOR ^、ビットシフト <<、>>)など、さまざまな演算が可能です。
また、これらの算術演算は整数に限定されます。Bash はデフォルトで浮動小数点数をサポートしていないため、浮動小数点演算を行いたい場合は bc や awk のような外部プログラムを使用する必要があります。

リダイレクト

リダイレクト(Redirection)は、UnixやLinuxのシェルスクリプトにおいて、標準入力(stdin)、標準出力(stdout)、標準エラー出力(stderr)の流れを制御する手段です。これにより、コマンドの出力をファイルに書き込んだり、ファイルから入力を読み込んだり、または他のコマンドへ出力を渡したりすることができます。

標準出力のリダイレクト (> と >>)

  • >:コマンドの標準出力をファイルに書き込みます。ファイルが既に存在する場合は上書きします。

  • >>:コマンドの標準出力をファイルに追記します。ファイルが存在しない場合は新しく作成します。

echo "Hello, World!" > output.txt  # output.txt に "Hello, World!" を書き込む
echo "Another line." >> output.txt  # output.txt に "Another line." を追記する

標準エラー出力のリダイレクト (2>)

2>:コマンドの標準エラー出力をファイルに書き込みます。

ls not_exist_file 2> error.txt  # 存在しないファイルをlsし、エラーメッセージを error.txt に書き込む

標準出力と標準エラー出力の両方をリダイレクト (&>)

&>:標準出力と標準エラー出力の両方をファイルに書き込みます。

ls > output.txt 2>&1  # 標準出力と標準エラー出力の両方を output.txt に書き込む

標準入力のリダイレクト (<)

<:ファイルからの内容をコマンドの標準入力として使用します。

cat < input.txt  # input.txt の内容を cat コマンドに入力する

パイプライン (|)

|:あるコマンドの標準出力を別のコマンドの標準入力として使用します。

cat file.txt | grep "search term"  # file.txt の内容を grep コマンドに渡して検索する

これらのリダイレクトとパイプラインを使用することで、複雑なデータ処理やファイル操作を行うことができ、UnixやLinuxのシェルスクリプトの強力な機能の一部を形成しています。

オプション

シェルスクリプトやコマンドラインツールにおける「オプション」は、実行時の挙動をカスタマイズするために使用されるパラメーターや設定です。これらのオプションは主に以下の二つのカテゴリに分けられます。

1. コマンドラインオプション

コマンドラインオプションは、スクリプトやプログラムを実行する際にコマンドラインを介して指定されます。これらは通常、短いフラグ(例: `-v`)または長いフラグ(例: `--verbose`)の形で提供され、特定の機能を有効にしたり、特定の値をプログラムに渡したりします。

  • 短いオプション:一般的にハイフン (`-`) に続く単一の文字です。例: `-v`(一般的に「verbose」モードの切り替えに使われる)

  • 長いオプション:二つのハイフン (`--`) に続く単語または単語の組み合わせです。例: `--verbose`

  • オプションの引数:いくつかのオプションは追加の引数を取ります。例: `-o filename` または `--output filename`

2. シェルのセットオプション

シェルのセットオプションは、シェルスクリプトの実行中の挙動を変更するために使われます。これらは `set` コマンドを使用して設定され、シェルのエラー処理、デバッグ情報の表示、オプションの展開などに関わります。

  • `set -e`:スクリプトがエラーを出した場合に直ちに終了する。

  • `set -x`:スクリプトの実行中に各コマンドを表示する(デバッグに有用)。

  • `set -u`:未定義の変数を参照した場合にエラーを出す。

注意点

  • コマンドラインオプションは、特定のコマンドやスクリプトに固有のものであり、それらの機能や使い方に依存します。

  • シェルのセットオプションは、シェルスクリプトの実行中にその挙動を変えるために使われますが、これらはスクリプト全体に影響を及ぼすことがあります。

  • コマンドやスクリプトによっては、オプションの後に追加の引数が必要になることがあります。

  • オプションとその引数の組み合わせや順序によって、コマンドやスクリプトの動作が大きく変わることがあります。

オプションを効果的に使用することで、プログラムやスクリプトの柔軟性と使い勝手が大きく向上します。プログラムやスクリプトを使用する際は、そのドキュメントやヘルプファイルを参照して、利用可能なオプションを確認することが重要です。


`test` コマンド

`test` コマンドは、UnixやLinuxのシェルスクリプトにおいて、さまざまな条件式を評価するために使用されるコマンドです。このコマンドは条件が真か偽かを判断し、その結果に基づいてスクリプトの実行フローを制御します。

基本的な機能:

`test` コマンドは以下のような条件をテストすることができます:

  1. 文字列のテスト:

    • 文字列が空かどうか、または二つの文字列が等しいかどうかをテストします。

    • 例: `test -z "$string"`(`$string` が空かどうかをチェック)

  2. 数値の比較:

    • 数値が等しい、より大きい、より小さいなどを比較します。

    • 例: `test $num1 -eq $num2`(`$num1` と `$num2` が等しいかをチェック)

  3. ファイルの状態のチェック:

    • ファイルが存在するか、読み取り可能か、書き込み可能か、特定の種類かどうかをテストします。

    • 例: `test -e filename`(ファイルが存在するかをチェック)

使用法:

`test` コマンドの一般的な構文は以下の通りです:

test condition

ここで `condition` は評価する条件です。条件が真の場合、`test` コマンドは 0(成功)を返し、偽の場合は 0 以外(失敗)を返します。

`[ ]` との関係:

`[ ]` は `test` コマンドの同義語で、より一般的に使用されます。`[ ]` を使用すると、同じ条件をより読みやすい形で記述できます。例えば、`test -z "$string"` は `[ -z "$string" ]` と書くことができます。

使用例:

if test -f "myfile.txt"; then
    echo "myfile.txt exists."
fi

# 上記は以下と同等です:
if [ -f "myfile.txt" ]; then
    echo "myfile.txt exists."
fi

`test` コマンドは、シェルスクリプトにおける条件分岐のための基本的かつ強力なツールです。

シェルスクリプトにおいては、様々なテスト式(条件式)が利用可能です。これらのテスト式は、ファイルの状態をチェックしたり、文字列や数値を比較したりするために使われます。以下にいくつかの一般的なテスト式を挙げます:

ファイルのテスト

  1. ファイルの存在: `-e`

    • `[ -e FILE ]`:ファイルまたはディレクトリが存在するかどうかをテストします。

  2. ファイルの種類: `-f`, `-d`

    • `[ -f FILE ]`:指定されたファイルが通常のファイルであるかどうかをテストします。

    • `[ -d FILE ]`:指定されたファイルがディレクトリであるかどうかをテストします。

  3. ファイルの権限: `-r`, `-w`, `-x`

    • `[ -r FILE ]`:ファイルが読み込み可能かどうかをテストします。

    • `[ -w FILE ]`:ファイルが書き込み可能かどうかをテストします。

    • `[ -x FILE ]`:ファイルが実行可能かどうかをテストします。

文字列のテスト

  1. 文字列の比較: `=`, `!=`

    • `[ STRING1 = STRING2 ]`:二つの文字列が等しいかどうかをテストします。

    • `[ STRING1 != STRING2 ]`:二つの文字列が異なるかどうかをテストします。

  2. 文字列の長さ: `-z`, `-n`

    • `[ -z STRING ]`:文字列が空(長さが0)かどうかをテストします。

    • `[ -n STRING ]`:文字列が非空(長さが0でない)かどうかをテストします。

数値のテスト

  1. 数値の比較: `-eq`, `-ne`, `-lt`, `-le`, `-gt`, `-ge`

    • `[ NUM1 -eq NUM2 ]`:二つの数値が等しいかどうかをテストします。

    • `[ NUM1 -ne NUM2 ]`:二つの数値が異なるかどうかをテストします。

    • `[ NUM1 -lt NUM2 ]`:NUM1 が NUM2 より小さいかどうかをテストします。

    • `[ NUM1 -le NUM2 ]`:NUM1 が NUM2 以下かどうかをテストします。

    • `[ NUM1 -gt NUM2 ]`:NUM1 が NUM2 より大きいかどうかをテストします。

    • `[ NUM1 -ge NUM2 ]`:NUM1 が NUM2 以上かどうかをテストします。

これらのテスト式は、`if` 文や `while` ループ内で条件を評価する際によく使用されます。また、`[ ]` と `[[ ]]` の両方でこれらのテストを使用することができますが、`[[ ]]` の方が若干柔軟な構文を持ち、一部のエラーを防ぐことができます。

この記事が気に入ったらサポートをしてみませんか?