shellscript
差分
このページの2つのバージョン間の差分を表示します。
両方とも前のリビジョン前のリビジョン次のリビジョン | 前のリビジョン | ||
shellscript [2019/05/21 02:50] – [ランダム文字列を生成] nullpon | shellscript [2025/10/11 16:48] (現在) – nullpon | ||
---|---|---|---|
行 1: | 行 1: | ||
====== ShellScript ====== | ====== ShellScript ====== | ||
+ | |||
+ | ===== bash ===== | ||
+ | |||
+ | シェルスクリプトはbashをターゲットに作成する。POSIX互換のシェルの方がポータビリティが高いが今時bashがない環境は少ない。 | ||
+ | |||
+ | < | ||
+ | #!/bin/bash -eu | ||
+ | |||
+ | ... | ||
+ | </ | ||
+ | |||
+ | そんなbashがない環境の代表がalpine。dockerでシェルスクリプトを起動するならdebianやubuntuが良いだろう | ||
===== shの実行オプション ===== | ===== shの実行オプション ===== | ||
行 6: | 行 18: | ||
* -x 変数を展開した状態で実際に実行されるコマンドを標準エラー出力に書き出す | * -x 変数を展開した状態で実際に実行されるコマンドを標準エラー出力に書き出す | ||
* -u 未定義の変数があれば処理を打ち切る | * -u 未定義の変数があれば処理を打ち切る | ||
+ | * -C noclobberオプションを有効にする(リダイレクトでファイルを上書きしようとするとエラーになる、追記はOK) | ||
shebangに追加されることが多い | shebangに追加されることが多い | ||
行 17: | 行 30: | ||
===== testコマンド ===== | ===== testコマンド ===== | ||
- | < | + | < |
test -f ./hoge.txt && echo " | test -f ./hoge.txt && echo " | ||
行 42: | 行 55: | ||
==== [[ ]] ==== | ==== [[ ]] ==== | ||
- | 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: | 行 84: | ||
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を送信) |
while read line | while read line | ||
do | do | ||
行 88: | 行 126: | ||
EOS | EOS | ||
| | ||
+ | | ||
+ | ===== trap ===== | ||
+ | |||
+ | ==== シグナルのハンドリング ==== | ||
+ | |||
+ | <code bash> | ||
+ | trap "echo trap sigint" | ||
+ | |||
+ | while :; do sleep 1; done | ||
+ | </ | ||
+ | |||
+ | SIGINTをトラップすると、Ctrl-cで終了できなくなるので注意。またSIGKILLはトラップできない。 | ||
+ | |||
+ | ==== EXITで終了時処理 ==== | ||
+ | |||
+ | 基本はシグナルのハンドリングだが、EXITとERRという疑似シグナルが利用できる。例えばmktempで作成した一時ファイルをスクリプト終了時に削除するなどの処理をEXITと組合わせて書ける。 | ||
+ | |||
+ | <code bash> | ||
+ | hoge=/ | ||
+ | mktemp $hoge | ||
+ | |||
+ | |||
+ | trap "rm $hoge" EXIT | ||
+ | </ | ||
| | ||
===== テクニック ===== | ===== テクニック ===== | ||
行 120: | 行 182: | ||
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 |
</ | </ | ||
行 135: | 行 199: | ||
===== 変数参照 ===== | ===== 変数参照 ===== | ||
- | < | + | < |
${HOGE: | ${HOGE: | ||
- | ${HOGE: | + | ${HOGE: |
${HOGE: | ${HOGE: | ||
${HOGE:? | ${HOGE:? | ||
</ | </ | ||
+ | ===== シェル変数の加工 ===== | ||
+ | |||
+ | 指定位置で切り取り | ||
+ | |||
+ | <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# | ||
行 159: | 行 269: | ||
コロンは何もしないビルトインコマンド | コロンは何もしないビルトインコマンド | ||
- | < | + | < |
: hogehoge | : hogehoge | ||
</ | </ | ||
行 165: | 行 275: | ||
変数HOGEが空だった場合、nyanを代入する | 変数HOGEが空だった場合、nyanを代入する | ||
- | < | + | < |
: ${HOGE: | : ${HOGE: | ||
</ | </ | ||
行 171: | 行 281: | ||
変数HOGEが空だった場合、Error HOGE is emptyと出力して終了 | 変数HOGEが空だった場合、Error HOGE is emptyと出力して終了 | ||
- | < | + | < |
: ${HOGE:?" | : ${HOGE:?" | ||
</ | </ | ||
行 177: | 行 287: | ||
可読性を考えると普通にifで書いた方がいいかも… | 可読性を考えると普通にifで書いた方がいいかも… | ||
- | < | + | < |
- | if [ -z "${HOGE}" | + | if [[ -z ${HOGE} |
echo "Error HOGE is empty" >&2 | echo "Error HOGE is empty" >&2 | ||
fi | fi | ||
行 196: | 行 306: | ||
ファイルディスクリプタ0番がterminalに紐づいている(=パイプやリダイレクトによるデータの入力がされていない) | ファイルディスクリプタ0番がterminalに紐づいている(=パイプやリダイレクトによるデータの入力がされていない) | ||
- | < | + | < |
if [ -t 0 ]; then | if [ -t 0 ]; then | ||
# パイプやリダイレクトされてない | # パイプやリダイレクトされてない | ||
行 213: | 行 323: | ||
'' | '' | ||
- | < | + | < |
# arg1.sh | # arg1.sh | ||
echo $# | echo $# | ||
行 220: | 行 330: | ||
</ | </ | ||
- | < | + | < |
$ ./arg1.sh a b c d | $ ./arg1.sh a b c d | ||
4 | 4 | ||
行 230: | 行 340: | ||
'' | '' | ||
- | < | + | < |
# arg2.sh | # arg2.sh | ||
echo $@ | echo $@ | ||
行 236: | 行 346: | ||
</ | </ | ||
- | < | + | < |
$ ./arg2.sh 1 2 3 | $ ./arg2.sh 1 2 3 | ||
1 2 3 | 1 2 3 | ||
行 242: | 行 352: | ||
</ | </ | ||
- | '' | + | '' |
- | < | + | |
+ | '' | ||
+ | |||
+ | < | ||
# arg3.sh | # arg3.sh | ||
node -p -e ' | node -p -e ' | ||
行 253: | 行 366: | ||
</ | </ | ||
- | < | + | < |
$ ./arg3.sh 1 2 3 | $ ./arg3.sh 1 2 3 | ||
1 2 3 | 1 2 3 | ||
行 263: | 行 376: | ||
'' | '' | ||
- | < | + | < |
# arg4.sh | # arg4.sh | ||
echo " | echo " | ||
行 270: | 行 383: | ||
</ | </ | ||
- | < | + | < |
$ ./arg4.sh 1 2 3 | $ ./arg4.sh 1 2 3 | ||
1 2 3 | 1 2 3 | ||
行 277: | 行 390: | ||
これらの挙動はシェル関数の引数でも同様である。 | これらの挙動はシェル関数の引数でも同様である。 | ||
+ | |||
+ | ===== ヒアドキュメント ===== | ||
+ | |||
+ | 変数に格納 | ||
+ | |||
+ | <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.1558407056.txt.gz · 最終更新: by nullpon