shellscript
差分
このページの2つのバージョン間の差分を表示します。
| 両方とも前のリビジョン前のリビジョン次のリビジョン | 前のリビジョン | ||
| shellscript [2020/03/31 07:48] – [変数参照] nullpon | shellscript [2025/10/31 02:06] (現在) – nullpon | ||
|---|---|---|---|
| 行 1: | 行 1: | ||
| ====== ShellScript ====== | ====== ShellScript ====== | ||
| + | |||
| + | ===== bash ===== | ||
| + | |||
| + | シェルスクリプトはbashをターゲットに作成する。POSIX互換のシェルの方がポータビリティが高いが今時bashがない環境は少ない。 | ||
| + | |||
| + | < | ||
| + | #!/bin/bash -eu | ||
| + | |||
| + | ... | ||
| + | </ | ||
| + | |||
| + | そんなbashがない環境の代表がalpine。dockerでシェルスクリプトを起動するならalpineを避けてdebianやubuntuをベースにすると良い。 | ||
| + | |||
| + | ===== シェルスクリプトの実行方法 ===== | ||
| + | |||
| + | - '' | ||
| + | - '' | ||
| + | - 実行権限を付与して直接実行(普段はこれ) | ||
| + | |||
| + | ==== sourceコマンドまたは. ==== | ||
| + | |||
| + | ファイル内に定義されているシェル関数や変数をシェルにロードする目的で使用する | ||
| + | |||
| + | <code sh> | ||
| + | HOGE=' | ||
| + | |||
| + | p() { | ||
| + | echo " | ||
| + | } | ||
| + | |||
| + | p | ||
| + | </ | ||
| + | |||
| + | これを実行すると、スクリプト終了後もpやHOGEがシェルに残る。 | ||
| + | |||
| + | <code sh> | ||
| + | $ source ./sample.sh | ||
| + | 1 | ||
| + | $ echo $HOGE | ||
| + | 1 | ||
| + | $ p | ||
| + | 1 | ||
| + | $ HOGE=2 | ||
| + | $ p | ||
| + | 2 | ||
| + | </ | ||
| + | |||
| + | '' | ||
| + | |||
| + | なお'' | ||
| + | |||
| + | <code sh> | ||
| + | $ . ./hoge.sh | ||
| + | $ . hoge.sh | ||
| + | </ | ||
| + | |||
| + | ==== bash, zshの引数として実行 ==== | ||
| + | |||
| + | |||
| + | 意図がなければ基本的には避けるべき実行方法 | ||
| + | |||
| + | <code sh> | ||
| + | $ bash sample.sh | ||
| + | </ | ||
| + | |||
| + | UNIXスクリプトは実行するシェル・ランタイムをshbangで指定する。以下のスクリプトはzshを想定しておりbashでは正しく動作しない、またはエラーになる可能性がある | ||
| + | |||
| + | <code sh> | ||
| + | #!/bin/zsh | ||
| + | |||
| + | name=" | ||
| + | echo ${name:u} | ||
| + | </ | ||
| + | |||
| + | <code sh> | ||
| + | $ zsh hoge.sh | ||
| + | HELLO | ||
| + | $ bash hoge.sh | ||
| + | hello | ||
| + | </ | ||
| + | |||
| + | 逆に自分がシェルスクリプトを書くときも何も考えず''# | ||
| + | |||
| + | ==== 実行権限を付与して直接実行 ==== | ||
| + | |||
| + | 普通はこれで実行する | ||
| + | |||
| + | <code sh> | ||
| + | $ chmod +x sample.sh | ||
| + | $ ./ | ||
| + | </ | ||
| ===== shの実行オプション ===== | ===== shの実行オプション ===== | ||
| 行 6: | 行 97: | ||
| * -x 変数を展開した状態で実際に実行されるコマンドを標準エラー出力に書き出す | * -x 変数を展開した状態で実際に実行されるコマンドを標準エラー出力に書き出す | ||
| * -u 未定義の変数があれば処理を打ち切る | * -u 未定義の変数があれば処理を打ち切る | ||
| + | * -C noclobberオプションを有効にする(リダイレクトでファイルを上書きしようとするとエラーになる、追記はOK) | ||
| shebangに追加されることが多い | shebangに追加されることが多い | ||
| 行 17: | 行 109: | ||
| ===== testコマンド ===== | ===== testコマンド ===== | ||
| - | < | + | < |
| test -f ./hoge.txt && echo " | test -f ./hoge.txt && echo " | ||
| 行 42: | 行 134: | ||
| ==== [[ ]] ==== | ==== [[ ]] ==== | ||
| - | bashの拡張、bashならこちらを使った方がバグが少ないので良い | + | testコマンドのbash拡張。単語分割やパス展開しないので、変数をクオートで囲む必要ない。 |
| - | 単語分割やパス展開しないので、変数をクオートで囲む必要ない | + | <code bash> |
| + | HOGE=" | ||
| - | <code sh> | + | [ $HOGE = "a b c" ] && echo " |
| - | $ HOGE=" | + | |
| - | $ [ $HOGE == "a b c" ] && echo " | + | |
| - | bash: [: too many arguments | + | |
| - | $ [[ $HOGE == "a b c" ]] && echo " | + | |
| - | 一致 | + | |
| - | $ HOGE=hoge.* | + | [ "$HOGE" |
| - | $ [ $HOGE == "hoge.*" ] && echo " | + | |
| - | 不一致 | + | [[ $HOGE = "a b c" ]] && echo " |
| - | $ [[ $HOGE == "hoge.*" ]] && echo " | + | |
| - | 一致 | + | |
| </ | </ | ||
| + | |||
| + | <code bash> | ||
| + | HOGE=" | ||
| + | |||
| + | [ $HOGE = " | ||
| + | |||
| + | [ " | ||
| + | |||
| + | [[ $HOGE = " | ||
| + | </ | ||
| + | |||
| + | zshでは '' | ||
| ===== read ===== | ===== read ===== | ||
| 行 65: | 行 163: | ||
| read line | read line | ||
| echo $line | echo $line | ||
| + | |||
| + | プロンプトを出して入力を促す | ||
| + | |||
| + | echo -n "User Name: " | ||
| + | read username | ||
| + | echo $username | ||
| + | | ||
| + | zshでは以下のようにかける | ||
| + | |||
| + | read " | ||
| + | echo $username | ||
| + | | ||
| + | 入力値をマスクしたい場合はread -s(決定時の改行も出力されなくなるのでechoを挟むとよい) | ||
| + | |||
| + | read -s " | ||
| + | tty -s && echo | ||
| + | echo $password | shasum -a 256 | ||
| + | |||
| + | |||
| | | ||
| 標準入力が尽きるまで行を読み取る(Ctrl-DでEOFを送信) | 標準入力が尽きるまで行を読み取る(Ctrl-DでEOFを送信) | ||
| 行 93: | 行 210: | ||
| ==== シグナルのハンドリング ==== | ==== シグナルのハンドリング ==== | ||
| - | < | + | < |
| trap "echo trap sigint" | trap "echo trap sigint" | ||
| 行 105: | 行 222: | ||
| 基本はシグナルのハンドリングだが、EXITとERRという疑似シグナルが利用できる。例えばmktempで作成した一時ファイルをスクリプト終了時に削除するなどの処理をEXITと組合わせて書ける。 | 基本はシグナルのハンドリングだが、EXITとERRという疑似シグナルが利用できる。例えばmktempで作成した一時ファイルをスクリプト終了時に削除するなどの処理をEXITと組合わせて書ける。 | ||
| - | < | + | < |
| hoge=/ | hoge=/ | ||
| mktemp $hoge | mktemp $hoge | ||
| 行 144: | 行 261: | ||
| 0-9A-Za-zのランダムな文字列を作成する。mac用 | 0-9A-Za-zのランダムな文字列を作成する。mac用 | ||
| - | < | + | < |
| - | $ cat /dev/random | base64 | fold -w 16 | egrep -v " | + | cat /dev/random | base64 | fold -w 16 | egrep -v " |
| + | </ | ||
| - | $ head -c 100 /dev/random | base64 | tr -d " | + | <code bash> |
| + | head -c 100 /dev/random | base64 | tr -d " | ||
| </ | </ | ||
| セキュアな必要がないならば | セキュアな必要がないならば | ||
| - | < | + | < |
| - | $ shasum <(ls -al) | cut -d " " -f 1 | + | shasum <(ls -al) | cut -d " " -f 1 |
| </ | </ | ||
| 行 159: | 行 278: | ||
| ===== 変数参照 ===== | ===== 変数参照 ===== | ||
| - | < | + | < |
| ${HOGE: | ${HOGE: | ||
| ${HOGE: | ${HOGE: | ||
| 行 166: | 行 285: | ||
| </ | </ | ||
| + | ===== シェル変数の加工 ===== | ||
| + | |||
| + | 指定位置で切り取り | ||
| + | |||
| + | <code bash> | ||
| + | x=abcdefg | ||
| + | echo ${x: | ||
| + | </ | ||
| + | |||
| + | 変数の値の先頭・末尾でマッチした部分を削除する | ||
| + | |||
| + | <code bash> | ||
| + | x=hogehogefugafuga | ||
| + | |||
| + | echo ${x# | ||
| + | |||
| + | echo ${x%fuga} | ||
| + | |||
| + | echo ${x# | ||
| + | |||
| + | echo ${x## | ||
| + | |||
| + | echo ${x%f*a} | ||
| + | |||
| + | echo ${x%%f*a} | ||
| + | </ | ||
| + | |||
| + | 文字列置換 | ||
| + | |||
| + | <code bash> | ||
| + | echo ${var/ | ||
| + | |||
| + | echo ${var// | ||
| + | </ | ||
| + | |||
| + | |||
| + | 使用例:まとめてリネーム、拡張子まとめて変更 | ||
| + | <code bash> | ||
| + | $ ls | ||
| + | a.txt b.txt c.txt | ||
| + | |||
| + | $ for i in `ls`; do mv $i ${i%.txt}.php; | ||
| + | |||
| + | $ls | ||
| + | a.php b.php c.php | ||
| + | </ | ||
| ===== パラメータ展開 ===== | ===== パラメータ展開 ===== | ||
| 例 | 例 | ||
| - | < | + | < |
| HOGE=" | HOGE=" | ||
| echo ${HOGE# | echo ${HOGE# | ||
| 行 183: | 行 348: | ||
| コロンは何もしないビルトインコマンド | コロンは何もしないビルトインコマンド | ||
| - | < | + | < |
| : hogehoge | : hogehoge | ||
| </ | </ | ||
| 行 189: | 行 354: | ||
| 変数HOGEが空だった場合、nyanを代入する | 変数HOGEが空だった場合、nyanを代入する | ||
| - | < | + | < |
| : ${HOGE: | : ${HOGE: | ||
| </ | </ | ||
| 行 195: | 行 360: | ||
| 変数HOGEが空だった場合、Error HOGE is emptyと出力して終了 | 変数HOGEが空だった場合、Error HOGE is emptyと出力して終了 | ||
| - | < | + | < |
| : ${HOGE:?" | : ${HOGE:?" | ||
| </ | </ | ||
| 行 201: | 行 366: | ||
| 可読性を考えると普通にifで書いた方がいいかも… | 可読性を考えると普通にifで書いた方がいいかも… | ||
| - | < | + | < |
| - | if [ -z "${HOGE}" | + | if [[ -z ${HOGE} |
| echo "Error HOGE is empty" >&2 | echo "Error HOGE is empty" >&2 | ||
| fi | fi | ||
| 行 220: | 行 385: | ||
| ファイルディスクリプタ0番がterminalに紐づいている(=パイプやリダイレクトによるデータの入力がされていない) | ファイルディスクリプタ0番がterminalに紐づいている(=パイプやリダイレクトによるデータの入力がされていない) | ||
| - | < | + | < |
| if [ -t 0 ]; then | if [ -t 0 ]; then | ||
| # パイプやリダイレクトされてない | # パイプやリダイレクトされてない | ||
| 行 237: | 行 402: | ||
| '' | '' | ||
| - | < | + | < |
| # arg1.sh | # arg1.sh | ||
| echo $# | echo $# | ||
| 行 244: | 行 409: | ||
| </ | </ | ||
| - | < | + | < |
| $ ./arg1.sh a b c d | $ ./arg1.sh a b c d | ||
| 4 | 4 | ||
| 行 254: | 行 419: | ||
| '' | '' | ||
| - | < | + | < |
| # arg2.sh | # arg2.sh | ||
| echo $@ | echo $@ | ||
| 行 260: | 行 425: | ||
| </ | </ | ||
| - | < | + | < |
| $ ./arg2.sh 1 2 3 | $ ./arg2.sh 1 2 3 | ||
| 1 2 3 | 1 2 3 | ||
| 行 266: | 行 431: | ||
| </ | </ | ||
| - | '' | + | '' |
| - | < | + | |
| + | '' | ||
| + | |||
| + | < | ||
| # arg3.sh | # arg3.sh | ||
| node -p -e ' | node -p -e ' | ||
| 行 277: | 行 445: | ||
| </ | </ | ||
| - | < | + | < |
| $ ./arg3.sh 1 2 3 | $ ./arg3.sh 1 2 3 | ||
| 1 2 3 | 1 2 3 | ||
| 行 287: | 行 455: | ||
| '' | '' | ||
| - | < | + | < |
| # arg4.sh | # arg4.sh | ||
| echo " | echo " | ||
| 行 294: | 行 462: | ||
| </ | </ | ||
| - | < | + | < |
| $ ./arg4.sh 1 2 3 | $ ./arg4.sh 1 2 3 | ||
| 1 2 3 | 1 2 3 | ||
| 行 301: | 行 469: | ||
| これらの挙動はシェル関数の引数でも同様である。 | これらの挙動はシェル関数の引数でも同様である。 | ||
| + | |||
| + | ===== ヒアドキュメント ===== | ||
| + | |||
| + | 変数に格納 | ||
| + | |||
| + | <code bash> | ||
| + | val=$(cat << ' | ||
| + | hoge | ||
| + | fuga | ||
| + | piyo | ||
| + | EOS | ||
| + | ) | ||
| + | </ | ||
| + | |||
| + | |||
| + | 標準入力に渡す | ||
| + | |||
| + | <code bash> | ||
| + | while read -r line | ||
| + | do | ||
| + | echo $line | ||
| + | done << ' | ||
| + | hoge | ||
| + | fuga | ||
| + | piyo | ||
| + | EOS | ||
| + | ) | ||
| + | </ | ||
| + | |||
| + | |||
| + | 一度変数を経由する。''<<<'' | ||
| + | |||
| + | <code bash> | ||
| + | val=$(cat << ' | ||
| + | hoge | ||
| + | fuga | ||
| + | piyo | ||
| + | EOS | ||
| + | ) | ||
| + | |||
| + | while read -r line | ||
| + | do | ||
| + | echo $line | ||
| + | done <<< | ||
| + | </ | ||
| + | |||
| + | クオートの有無は変数展開するかしないか | ||
| + | |||
| + | <code bash> | ||
| + | val=' | ||
| + | |||
| + | while read -r line | ||
| + | do | ||
| + | echo $line | ||
| + | done << " | ||
| + | ${val} | ||
| + | ${val} | ||
| + | ${val} | ||
| + | EOF | ||
| + | </ | ||
| + | |||
| + | クオートありの場合は変数展開されずに以下のように出力される | ||
| + | |||
| + | < | ||
| + | ${val} | ||
| + | ${val} | ||
| + | ${val} | ||
| + | </ | ||
| + | |||
shellscript.1585640922.txt.gz · 最終更新: by nullpon